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