Init
This commit is contained in:
commit
5fd6457c7a
7 changed files with 247 additions and 0 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*.cr]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
/docs/
|
||||
/lib/
|
||||
/bin/
|
||||
/.shards/
|
||||
*.dwarf
|
||||
|
||||
# Libraries don't need dependency lock
|
||||
# Dependencies will be locked in applications that use them
|
||||
/shard.lock
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Dominic Grimm <dominic.grimm@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
39
README.md
Normal file
39
README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# service
|
||||
|
||||
TODO: Write a description here
|
||||
|
||||
## Installation
|
||||
|
||||
1. Add the dependency to your `shard.yml`:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
service:
|
||||
git: https://git.dergrimm.net/dergrimm/service.git
|
||||
```
|
||||
|
||||
2. Run `shards install`
|
||||
|
||||
## Usage
|
||||
|
||||
```crystal
|
||||
require "service"
|
||||
```
|
||||
|
||||
TODO: Write usage instructions here
|
||||
|
||||
## Development
|
||||
|
||||
TODO: Write development instructions here
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork it
|
||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
4. Push to the branch (`git push origin my-new-feature`)
|
||||
5. Create a new Pull Request
|
||||
|
||||
## Contributors
|
||||
|
||||
- [Dominic Grimm](https://git.dergrimm.net/dergrimm) - creator and maintainer
|
42
examples/example.cr
Normal file
42
examples/example.cr
Normal file
|
@ -0,0 +1,42 @@
|
|||
require "../src/service"
|
||||
require "log"
|
||||
|
||||
class MessageService < Service
|
||||
Log = ::Log.for(self)
|
||||
|
||||
@@i = 0
|
||||
|
||||
getter message
|
||||
getter delay
|
||||
getter times
|
||||
|
||||
def initialize(@message : String, @delay : Int32, @times : Int32)
|
||||
end
|
||||
|
||||
def run(_unit : Unit) : Service::Unit?
|
||||
puts @message
|
||||
@@i += 1
|
||||
Log.info { @@i }
|
||||
sleep @delay
|
||||
|
||||
if @@i < @times
|
||||
Service::Unit.new(self)
|
||||
else
|
||||
Log.info { "Done." }
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Runner < Service::Runner
|
||||
def starters : Array(Service::Starter)
|
||||
[
|
||||
Service::AsynchronousStarter.new([
|
||||
MessageService.new("Hello world from AsynchronousStarter!", delay: 1, times: 5).as(Service),
|
||||
]).as(Service::Starter),
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
Runner.new.run
|
13
shard.yml
Normal file
13
shard.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
name: service
|
||||
version: 0.1.0
|
||||
|
||||
authors:
|
||||
- Dominic Grimm <dominic.grimm@gmail.com>
|
||||
|
||||
crystal: 1.3.2
|
||||
|
||||
license: MIT
|
||||
|
||||
dependencies:
|
||||
version_from_shard:
|
||||
github: hugopl/version_from_shard
|
114
src/service.cr
Normal file
114
src/service.cr
Normal file
|
@ -0,0 +1,114 @@
|
|||
require "version_from_shard"
|
||||
|
||||
abstract class Service
|
||||
VersionFromShard.declare
|
||||
|
||||
abstract def run(unit : Unit) : Unit?
|
||||
|
||||
def handle(unit : Unit?) : Unit?
|
||||
if unit
|
||||
unit.handle(self)
|
||||
end
|
||||
end
|
||||
|
||||
class Unit
|
||||
property service
|
||||
property handler_proc
|
||||
|
||||
alias Handler = (self, Service) -> Unit?
|
||||
|
||||
DEFAULT_HANLDER = ->(unit : self, service : Service) { service.run(unit).as(Unit?) }
|
||||
NO_RESTART_HANDLER = ->(_unit : self, _service : Service) { nil }
|
||||
|
||||
def initialize(@service : Service, @handler_proc : Handler = DEFAULT_HANLDER)
|
||||
end
|
||||
|
||||
def initialize(service : Service, &handler_proc : Handler)
|
||||
initialize(service, handler_proc)
|
||||
end
|
||||
|
||||
def handle(service : Service) : Unit?
|
||||
handler_proc.call(self, service)
|
||||
end
|
||||
end
|
||||
|
||||
abstract class Starter
|
||||
abstract def logic : Array(Service)
|
||||
|
||||
abstract def start : self
|
||||
|
||||
def self.handle(service : Service) : Nil
|
||||
unit = service.run(Unit.new(service))
|
||||
|
||||
if unit
|
||||
while unit = service.handle(unit.not_nil!)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
abstract class ArrayStarter < Starter
|
||||
getter services
|
||||
|
||||
def initialize(@services : Array(Service))
|
||||
end
|
||||
|
||||
def logic : Array(Service)
|
||||
@services
|
||||
end
|
||||
end
|
||||
|
||||
class SynchronousStarter < ArrayStarter
|
||||
def start : self
|
||||
l = logic
|
||||
|
||||
channel = Channel(Nil).new(l.size)
|
||||
logic.each do |service|
|
||||
spawn do
|
||||
Starter.handle(service)
|
||||
channel.send(nil)
|
||||
end
|
||||
end
|
||||
l.size.times do
|
||||
channel.receive
|
||||
end
|
||||
Fiber.yield
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
class AsynchronousStarter < ArrayStarter
|
||||
def start : self
|
||||
logic.each do |service|
|
||||
Starter.handle(service)
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
abstract class Runner
|
||||
Log = Log.for(self)
|
||||
|
||||
abstract def starters : Array(Starter)
|
||||
|
||||
def run : self
|
||||
s = starters
|
||||
|
||||
channel = Channel(Nil).new(s.size)
|
||||
s.each do |starter|
|
||||
spawn do
|
||||
starter.start
|
||||
channel.send(nil)
|
||||
end
|
||||
end
|
||||
s.size.times do
|
||||
channel.receive
|
||||
end
|
||||
Fiber.yield
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
Reference in a new issue