kamerling 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -13
- data/Gemfile +0 -1
- data/Gemfile.lock +64 -64
- data/README.md +18 -1
- data/Rakefile +5 -3
- data/bin/kamerling +1 -1
- data/config/reek.yml +20 -3
- data/kamerling.gemspec +16 -13
- data/lib/kamerling.rb +2 -28
- data/lib/kamerling/addr.rb +17 -3
- data/lib/kamerling/client.rb +10 -11
- data/lib/kamerling/core_extensions/main.rb +14 -14
- data/lib/kamerling/dispatch.rb +13 -0
- data/lib/kamerling/handler.rb +16 -25
- data/lib/kamerling/http_api.rb +50 -34
- data/lib/kamerling/logging.rb +36 -16
- data/lib/kamerling/mapper.rb +33 -0
- data/lib/kamerling/message.rb +50 -37
- data/lib/kamerling/migrations/2_results_received_at.rb +7 -0
- data/lib/kamerling/migrations/3_dispatches.rb +17 -0
- data/lib/kamerling/migrations/4_registrations_registered_at.rb +7 -0
- data/lib/kamerling/migrations/5_clients_type.rb +7 -0
- data/lib/kamerling/net_dispatcher.rb +12 -7
- data/lib/kamerling/project.rb +7 -3
- data/lib/kamerling/receiver.rb +38 -10
- data/lib/kamerling/registrar.rb +45 -8
- data/lib/kamerling/registration.rb +9 -10
- data/lib/kamerling/repo.rb +33 -26
- data/lib/kamerling/repos.rb +52 -45
- data/lib/kamerling/result.rb +10 -11
- data/lib/kamerling/server/http.rb +28 -21
- data/lib/kamerling/server/sock.rb +32 -24
- data/lib/kamerling/server/tcp.rb +23 -15
- data/lib/kamerling/server/udp.rb +24 -16
- data/lib/kamerling/server_runner.rb +30 -41
- data/lib/kamerling/settings.rb +28 -0
- data/lib/kamerling/task.rb +7 -7
- data/lib/kamerling/task_dispatcher.rb +31 -22
- data/lib/kamerling/uuid.rb +13 -11
- data/lib/kamerling/uuid_entity.rb +23 -9
- data/lib/kamerling/value.rb +13 -0
- data/lib/kamerling/views/clients.slim +3 -1
- data/lib/kamerling/views/project.slim +8 -4
- data/lib/kamerling/views/projects.slim +7 -1
- data/spec/kamerling/addr_spec.rb +32 -22
- data/spec/kamerling/client_spec.rb +9 -5
- data/spec/kamerling/core_extensions/main_spec.rb +18 -13
- data/spec/kamerling/dispatch_spec.rb +16 -0
- data/spec/kamerling/handler_spec.rb +24 -34
- data/spec/kamerling/http_api_spec.rb +94 -73
- data/spec/kamerling/logging_spec.rb +93 -62
- data/spec/kamerling/mapper_spec.rb +151 -0
- data/spec/kamerling/message_spec.rb +73 -49
- data/spec/kamerling/net_dispatcher_spec.rb +22 -16
- data/spec/kamerling/receiver_spec.rb +29 -19
- data/spec/kamerling/registrar_spec.rb +43 -15
- data/spec/kamerling/registration_spec.rb +17 -0
- data/spec/kamerling/repo_spec.rb +63 -47
- data/spec/kamerling/repos_spec.rb +121 -109
- data/spec/kamerling/result_spec.rb +16 -0
- data/spec/kamerling/server/http_spec.rb +19 -14
- data/spec/kamerling/server/tcp_spec.rb +41 -35
- data/spec/kamerling/server/udp_spec.rb +40 -34
- data/spec/kamerling/server_runner_spec.rb +62 -53
- data/spec/kamerling/settings_spec.rb +36 -0
- data/spec/kamerling/task_dispatcher_spec.rb +38 -15
- data/spec/kamerling/task_spec.rb +9 -5
- data/spec/kamerling/uuid_entity_spec.rb +53 -25
- data/spec/kamerling/uuid_spec.rb +19 -16
- data/spec/kamerling/value_spec.rb +21 -0
- data/spec/spec_helper.rb +3 -6
- metadata +54 -8
- data/lib/kamerling/core_extensions.rb +0 -1
@@ -1,17 +1,17 @@
|
|
1
|
-
module Kamerling
|
2
|
-
|
1
|
+
module Kamerling
|
2
|
+
module CoreExtensions
|
3
|
+
module Main
|
4
|
+
module_function
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def warn_off
|
7
|
+
verbose = $VERBOSE
|
8
|
+
$VERBOSE = false
|
9
|
+
yield
|
10
|
+
ensure
|
11
|
+
$VERBOSE = verbose
|
12
|
+
end
|
13
|
+
end
|
8
14
|
end
|
15
|
+
end
|
9
16
|
|
10
|
-
|
11
|
-
verbose = $VERBOSE
|
12
|
-
$VERBOSE = false
|
13
|
-
yield
|
14
|
-
ensure
|
15
|
-
$VERBOSE = verbose
|
16
|
-
end
|
17
|
-
end end end
|
17
|
+
include Kamerling::CoreExtensions::Main
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'addr'
|
2
|
+
require_relative 'client'
|
3
|
+
require_relative 'project'
|
4
|
+
require_relative 'task'
|
5
|
+
require_relative 'uuid_entity'
|
6
|
+
|
7
|
+
module Kamerling
|
8
|
+
class Dispatch < UUIDEntity
|
9
|
+
attrs addr: Addr, client: Client, dispatched_at: Time, project: Project,
|
10
|
+
task: Task
|
11
|
+
defaults dispatched_at: -> (*) { Time.now }
|
12
|
+
end
|
13
|
+
end
|
data/lib/kamerling/handler.rb
CHANGED
@@ -1,29 +1,20 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative 'receiver'
|
2
|
+
require_relative 'registrar'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
process Message.new(input), addr
|
10
|
-
rescue Message::UnknownType => exception
|
11
|
-
raise UnknownInput, exception.message
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :receiver, :registrar
|
15
|
-
private :receiver, :registrar
|
16
|
-
|
17
|
-
private
|
4
|
+
module Kamerling
|
5
|
+
class Handler
|
6
|
+
def initialize(receiver: Receiver, registrar: Registrar)
|
7
|
+
@receiver, @registrar = receiver, registrar
|
8
|
+
end
|
18
9
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
when :RSLT
|
25
|
-
receiver.receive addr: addr, client_uuid: message.client_uuid,
|
26
|
-
data: message.payload, task_uuid: message.task_uuid
|
10
|
+
def handle(message, addr)
|
11
|
+
case message.type
|
12
|
+
when :RGST then registrar.register addr: addr, message: message
|
13
|
+
when :RSLT then receiver.receive addr: addr, message: message
|
14
|
+
end
|
27
15
|
end
|
16
|
+
|
17
|
+
attr_reader :receiver, :registrar
|
18
|
+
private :receiver, :registrar
|
28
19
|
end
|
29
|
-
end
|
20
|
+
end
|
data/lib/kamerling/http_api.rb
CHANGED
@@ -1,38 +1,54 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'sinatra/base'
|
3
3
|
require 'slim'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
4
|
+
require_relative 'project'
|
5
|
+
require_relative 'repos'
|
6
|
+
require_relative 'task_dispatcher'
|
7
|
+
require_relative 'uuid'
|
8
|
+
|
9
|
+
module Kamerling
|
10
|
+
class HTTPAPI < Sinatra::Base
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
delegate %i(task_dispatcher repos) => :settings
|
14
|
+
|
15
|
+
configure { set task_dispatcher: TaskDispatcher.new, repos: Repos }
|
16
|
+
|
17
|
+
get '/' do
|
18
|
+
render_template :root
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/clients' do
|
22
|
+
render_template :clients, locals: { clients: repos.clients }
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/projects' do
|
26
|
+
render_template :projects, locals: { projects: repos.projects }
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/projects/:project_uuid' do
|
30
|
+
project = repos.project(params['project_uuid'])
|
31
|
+
clients = repos.clients_for(project)
|
32
|
+
tasks = repos.tasks_for(project)
|
33
|
+
render_template :project, locals: { clients: clients, tasks: tasks }
|
34
|
+
end
|
35
|
+
|
36
|
+
post '/projects' do
|
37
|
+
name = params.fetch('name')
|
38
|
+
uuid = params.fetch('uuid')
|
39
|
+
repos << Project.new(name: name, uuid: uuid)
|
40
|
+
redirect '/projects'
|
41
|
+
end
|
42
|
+
|
43
|
+
post '/projects/dispatch' do
|
44
|
+
task_dispatcher.dispatch_all
|
45
|
+
redirect '/projects'
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def render_template(template, locals: {})
|
51
|
+
warn_off { slim template, locals: locals }
|
52
|
+
end
|
20
53
|
end
|
21
|
-
|
22
|
-
get '/projects/:project_uuid' do
|
23
|
-
project = repos.project params['project_uuid']
|
24
|
-
clients = repos.clients_for project
|
25
|
-
tasks = repos.tasks_for project
|
26
|
-
warn_off { slim :project, locals: { clients: clients, tasks: tasks } }
|
27
|
-
end
|
28
|
-
|
29
|
-
post '/projects' do
|
30
|
-
uuid = params.fetch('uuid') { UUID.new }
|
31
|
-
repos << Project.new(name: params['name'], uuid: uuid)
|
32
|
-
redirect '/projects'
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
delegate repos: :settings
|
38
|
-
end end
|
54
|
+
end
|
data/lib/kamerling/logging.rb
CHANGED
@@ -1,32 +1,52 @@
|
|
1
1
|
require 'after_do'
|
2
2
|
require 'logger'
|
3
|
+
require_relative 'net_dispatcher'
|
4
|
+
require_relative 'server/sock'
|
3
5
|
|
4
|
-
module Kamerling
|
5
|
-
|
6
|
+
module Kamerling
|
7
|
+
class Logging
|
8
|
+
def self.log_to(logger = Logger.new($stdout))
|
9
|
+
new logger
|
10
|
+
end
|
6
11
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
def initialize(logger)
|
13
|
+
@logger = logger
|
14
|
+
log_dispatcher
|
15
|
+
log_server
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :logger
|
19
|
+
private :logger
|
11
20
|
|
12
|
-
class << self
|
13
21
|
private
|
14
22
|
|
15
|
-
def
|
23
|
+
def log_dispatcher
|
16
24
|
NetDispatcher.singleton_class.extend AfterDo
|
17
|
-
NetDispatcher.singleton_class.before
|
18
|
-
logger.debug "sent #{addr} #{
|
25
|
+
NetDispatcher.singleton_class.before(:dispatch) do |addr, message|
|
26
|
+
logger.debug "sent #{addr} #{message.to_hex}"
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
22
|
-
def
|
30
|
+
def log_server
|
23
31
|
Server::Sock.extend AfterDo
|
32
|
+
log_server_lifecycle
|
33
|
+
log_server_communication
|
34
|
+
end
|
35
|
+
|
36
|
+
def log_server_communication
|
37
|
+
Server::Sock.before(:handle) do |input, client_addr|
|
38
|
+
begin
|
39
|
+
logger.info "connect #{client_addr}"
|
40
|
+
logger.debug "received #{client_addr} #{Message.parse(input).to_hex}"
|
41
|
+
rescue Message::UnknownType
|
42
|
+
logger.debug "received #{client_addr} unknown message type"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def log_server_lifecycle
|
24
48
|
Server::Sock.before(:start) { |srv| logger.info "start #{srv.addr}" }
|
25
49
|
Server::Sock.after(:stop) { |srv| logger.info "stop #{srv.addr}" }
|
26
|
-
Server::Sock.before :handle do |input, client_addr|
|
27
|
-
logger.info "connect #{client_addr}"
|
28
|
-
logger.debug "received #{client_addr} #{input}"
|
29
|
-
end
|
30
50
|
end
|
31
51
|
end
|
32
|
-
end
|
52
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'addr'
|
2
|
+
|
3
|
+
module Kamerling
|
4
|
+
module Mapper
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def from_h(klass, hash, repos: Repos)
|
8
|
+
attributes = hash.map do |key, value|
|
9
|
+
case key
|
10
|
+
when :host, :port, :prot then [:addr, Addr.new(hash)]
|
11
|
+
when /_uuid$/ then object_pair_from(key, value, repos)
|
12
|
+
else [key, value]
|
13
|
+
end
|
14
|
+
end.to_h
|
15
|
+
klass.new(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def object_pair_from(key, value, repos)
|
19
|
+
type = key[/(.*)_uuid$/, 1].to_sym
|
20
|
+
[type, repos[Kamerling.const_get(type.capitalize)][value]]
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_h(object)
|
24
|
+
object.to_h.reduce({}) do |hash, (key, value)|
|
25
|
+
hash.merge case value
|
26
|
+
when Addr then value.to_h
|
27
|
+
when Hash then { :"#{key}_uuid" => value[:uuid] }
|
28
|
+
else { key => value }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/kamerling/message.rb
CHANGED
@@ -1,47 +1,60 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'equalizer'
|
2
|
+
require_relative 'uuid'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
4
|
+
module Kamerling
|
5
|
+
class Message
|
6
|
+
KNOWN_TYPES = %i(DATA PING RGST RSLT)
|
7
|
+
UnknownType = Class.new(RuntimeError)
|
9
8
|
|
10
|
-
|
11
|
-
@raw = raw
|
12
|
-
type = raw[0..3]
|
13
|
-
known_types = %w(DATA PING RGST RSLT)
|
14
|
-
fail UnknownType, type unless known_types.include? type or type.empty?
|
15
|
-
end
|
9
|
+
include Equalizer.new(:raw)
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
def self.build(client:, payload:, project:, task:, type:)
|
12
|
+
new([type, "\0\0\0\0\0\0\0\0\0\0\0\0", UUID.bin(client.uuid),
|
13
|
+
UUID.bin(project.uuid), UUID.bin(task.uuid), payload].join)
|
14
|
+
end
|
20
15
|
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
def self.parse(raw)
|
17
|
+
new(raw)
|
18
|
+
end
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
def initialize(raw)
|
21
|
+
@raw = raw
|
22
|
+
fail UnknownType, type unless KNOWN_TYPES.include?(type) or type.empty?
|
23
|
+
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
def client_type
|
26
|
+
raw[4..7].to_sym
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
def client_uuid
|
30
|
+
UUID[raw[16..31]]
|
31
|
+
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
def payload
|
34
|
+
raw[64..-1]
|
35
|
+
end
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
def project_uuid
|
38
|
+
UUID[raw[32..47]]
|
39
|
+
end
|
40
|
+
|
41
|
+
def task_uuid
|
42
|
+
UUID[raw[48..63]]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_hex
|
46
|
+
raw.unpack('H*').first.scan(/../).join(' ')
|
47
|
+
end
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
49
|
+
def to_s
|
50
|
+
raw
|
51
|
+
end
|
52
|
+
|
53
|
+
def type
|
54
|
+
raw[0..3].to_sym
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :raw
|
58
|
+
protected :raw
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Sequel.migration do
|
2
|
+
change do
|
3
|
+
create_table :dispatches do
|
4
|
+
uuid :uuid, primary_key: true
|
5
|
+
inet :host, null: false
|
6
|
+
integer :port, null: false
|
7
|
+
string :prot, null: false
|
8
|
+
timestamp :dispatched_at, null: false
|
9
|
+
foreign_key :client_uuid, :clients, index: true, null: false,
|
10
|
+
type: :uuid
|
11
|
+
foreign_key :project_uuid, :projects, index: true, null: false,
|
12
|
+
type: :uuid
|
13
|
+
foreign_key :task_uuid, :tasks, index: true, null: false,
|
14
|
+
type: :uuid
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,10 +1,15 @@
|
|
1
|
-
|
2
|
-
module_function
|
1
|
+
require 'socket'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Kamerling
|
4
|
+
module NetDispatcher
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def dispatch(addr, message)
|
8
|
+
bytes = message.to_s
|
9
|
+
case addr.prot
|
10
|
+
when :TCP then TCPSocket.open(*addr) { |socket| socket << bytes }
|
11
|
+
when :UDP then UDPSocket.new.send bytes, 0, *addr
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
|
-
end
|
15
|
+
end
|