kamerling 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/kamerling/server/tcp.rb
CHANGED
@@ -1,19 +1,27 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'socket'
|
2
|
+
require_relative '../addr'
|
3
|
+
require_relative 'sock'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
ensure
|
9
|
-
socket.close
|
10
|
-
end
|
5
|
+
module Kamerling
|
6
|
+
module Server
|
7
|
+
class TCP < Sock
|
8
|
+
private
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def handle_connection(socket)
|
11
|
+
client_addr = Addr[*socket.remote_address.ip_unpack, :TCP]
|
12
|
+
input = socket.read
|
13
|
+
handle input, client_addr
|
14
|
+
ensure
|
15
|
+
socket.close
|
16
|
+
end
|
17
|
+
|
18
|
+
def run_loop
|
19
|
+
Socket.tcp_server_loop(*addr) { |socket| handle_connection socket }
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
22
|
+
def wait_till_started
|
23
|
+
loop { break if addr.connectable? }
|
24
|
+
end
|
25
|
+
end
|
18
26
|
end
|
19
|
-
end
|
27
|
+
end
|
data/lib/kamerling/server/udp.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'socket'
|
2
|
+
require_relative '../addr'
|
3
|
+
require_relative 'sock'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
5
|
+
module Kamerling
|
6
|
+
module Server
|
7
|
+
class UDP < Sock
|
8
|
+
private
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
def handle_connection(socket)
|
11
|
+
input, conn = socket.recvfrom 2**16
|
12
|
+
client_addr = Addr[conn[3], conn[1], :UDP]
|
13
|
+
handle input, client_addr
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_loop
|
17
|
+
socket = UDPSocket.new.tap { |server| server.bind(*addr) }
|
18
|
+
loop { handle_connection socket if IO.select [socket] }
|
19
|
+
ensure
|
20
|
+
socket.close if socket
|
21
|
+
end
|
16
22
|
|
17
|
-
|
18
|
-
|
23
|
+
def wait_till_started
|
24
|
+
200.times { thread.run }
|
25
|
+
end
|
26
|
+
end
|
19
27
|
end
|
20
|
-
end
|
28
|
+
end
|
@@ -1,48 +1,37 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
servers.each(&:start)
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
attr_reader :args, :servers
|
23
|
-
private :args, :servers
|
1
|
+
require 'sequel'
|
2
|
+
require_relative 'addr'
|
3
|
+
require_relative 'repos'
|
4
|
+
require_relative 'server/http'
|
5
|
+
require_relative 'server/tcp'
|
6
|
+
require_relative 'server/udp'
|
7
|
+
require_relative 'settings'
|
8
|
+
|
9
|
+
module Kamerling
|
10
|
+
class ServerRunner
|
11
|
+
def initialize(args, classes: def_classes, orm: Sequel, repos: Repos)
|
12
|
+
settings = Settings.new(args)
|
13
|
+
repos.db = orm.connect(settings.db)
|
14
|
+
@servers = settings.server_addrs.map do |type, addr|
|
15
|
+
classes[type].new(addr: addr)
|
16
|
+
end
|
17
|
+
end
|
24
18
|
|
25
|
-
|
19
|
+
def join
|
20
|
+
servers.each(&:join)
|
21
|
+
end
|
26
22
|
|
27
|
-
|
23
|
+
def start
|
24
|
+
servers.each(&:start)
|
25
|
+
self
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
28
|
+
attr_reader :servers
|
29
|
+
private :servers
|
32
30
|
|
33
|
-
|
34
|
-
Settings.new 'sqlite::memory:', '127.0.0.1'
|
35
|
-
end
|
31
|
+
private
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
OptionParser.new do |opt|
|
40
|
-
opt.on("--db #{set.db}", String, 'database') { |db| set.db = db }
|
41
|
-
opt.on("--host #{set.host}", String, 'host') { |host| set.host = host }
|
42
|
-
opt.on('--http 0', Integer, 'HTTP port') { |http| set.http = http }
|
43
|
-
opt.on('--tcp 0', Integer, 'TCP port') { |tcp| set.tcp = tcp }
|
44
|
-
opt.on('--udp 0', Integer, 'UDP port') { |udp| set.udp = udp }
|
45
|
-
end.parse! args
|
33
|
+
def def_classes
|
34
|
+
{ http: Server::HTTP, tcp: Server::TCP, udp: Server::UDP }
|
46
35
|
end
|
47
36
|
end
|
48
|
-
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require_relative 'addr'
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module Kamerling
|
6
|
+
class Settings < Value
|
7
|
+
vals db: String, host: String, http: Integer, tcp: Integer, udp: Integer
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
super db: 'sqlite::memory:', host: '127.0.0.1'
|
11
|
+
OptionParser.new do |opt|
|
12
|
+
opt.on("--db #{db}", String, 'database') { |db| self.db = db }
|
13
|
+
opt.on("--host #{host}", String, 'host') { |host| self.host = host }
|
14
|
+
opt.on('--http 0', Integer, 'HTTP port') { |http| self.http = http }
|
15
|
+
opt.on('--tcp 0', Integer, 'TCP port') { |tcp| self.tcp = tcp }
|
16
|
+
opt.on('--udp 0', Integer, 'UDP port') { |udp| self.udp = udp }
|
17
|
+
end.parse! args
|
18
|
+
end
|
19
|
+
|
20
|
+
def server_addrs
|
21
|
+
{
|
22
|
+
http: Addr[host, http, :TCP],
|
23
|
+
tcp: Addr[host, tcp, :TCP],
|
24
|
+
udp: Addr[host, udp, :UDP],
|
25
|
+
}.select { |_, addr| addr.port }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/kamerling/task.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
attribute :done, Boolean, default: false
|
4
|
-
attribute :project, Project
|
1
|
+
require_relative 'project'
|
2
|
+
require_relative 'uuid_entity'
|
5
3
|
|
6
|
-
|
7
|
-
|
4
|
+
module Kamerling
|
5
|
+
class Task < UUIDEntity
|
6
|
+
attrs data: String, done: Boolean, project: Project
|
7
|
+
defaults done: false
|
8
8
|
end
|
9
|
-
end
|
9
|
+
end
|
@@ -1,29 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require_relative 'dispatch'
|
2
|
+
require_relative 'message'
|
3
|
+
require_relative 'net_dispatcher'
|
4
|
+
require_relative 'repos'
|
5
|
+
|
6
|
+
module Kamerling
|
7
|
+
class TaskDispatcher
|
8
|
+
def initialize(net_dispatcher: NetDispatcher, repos: Repos)
|
9
|
+
@net_dispatcher = net_dispatcher
|
10
|
+
@repos = repos
|
11
|
+
end
|
6
12
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
def dispatch_all
|
14
|
+
repos.projects.each do |project|
|
15
|
+
repos.free_clients_for(project).each do |client|
|
16
|
+
task = repos.next_task_for(project)
|
17
|
+
dispatch_task client: client, project: project, task: task if task
|
18
|
+
end
|
12
19
|
end
|
13
20
|
end
|
14
|
-
end
|
15
21
|
|
16
|
-
|
17
|
-
|
22
|
+
attr_reader :net_dispatcher, :repos
|
23
|
+
private :net_dispatcher, :repos
|
18
24
|
|
19
|
-
|
25
|
+
private
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
def dispatch_task(client:, project:, task:)
|
28
|
+
message = Message.build(client: client, payload: task.data,
|
29
|
+
project: project, task: task, type: :DATA)
|
30
|
+
dispatch = Dispatch.new(addr: client.addr, client: client,
|
31
|
+
project: project, task: task)
|
32
|
+
net_dispatcher.dispatch client.addr, message
|
33
|
+
client.busy = true
|
34
|
+
repos << client
|
35
|
+
repos << dispatch
|
36
|
+
end
|
28
37
|
end
|
29
|
-
end
|
38
|
+
end
|
data/lib/kamerling/uuid.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
|
3
|
-
module Kamerling
|
4
|
-
|
3
|
+
module Kamerling
|
4
|
+
module UUID
|
5
|
+
module_function
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def [](bin)
|
8
|
+
bin.unpack('H8H4H4H4H12').join('-')
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def bin(uuid)
|
12
|
+
[uuid.tr('-', '')].pack('H*')
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
def new
|
16
|
+
SecureRandom.uuid
|
17
|
+
end
|
16
18
|
end
|
17
|
-
end
|
19
|
+
end
|
@@ -1,15 +1,29 @@
|
|
1
|
+
require 'equalizer'
|
1
2
|
require 'virtus'
|
3
|
+
require_relative 'uuid'
|
2
4
|
|
3
|
-
module Kamerling
|
4
|
-
|
5
|
+
module Kamerling
|
6
|
+
class UUIDEntity
|
7
|
+
include Equalizer.new(:uuid)
|
5
8
|
|
6
|
-
|
9
|
+
include Virtus.model
|
7
10
|
|
8
|
-
|
11
|
+
attribute :uuid, String, default: -> (*) { UUID.new }
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
def self.attrs(hash = {})
|
14
|
+
hash.each { |name, klass| attribute name, klass }
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.defaults(hash = {})
|
18
|
+
hash.each do |name, default|
|
19
|
+
warn_off { attribute name, attribute_set[name].type, default: default }
|
20
|
+
end
|
21
|
+
end
|
13
22
|
|
14
|
-
|
15
|
-
|
23
|
+
def to_h
|
24
|
+
attributes.map do |key, value|
|
25
|
+
value.is_a?(UUIDEntity) ? [key, value.to_h] : [key, value]
|
26
|
+
end.to_h
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -2,5 +2,7 @@ nav
|
|
2
2
|
ul#clients
|
3
3
|
- clients.each do |client|
|
4
4
|
li
|
5
|
-
a
|
5
|
+
a(data-addr=client.addr data-busy=client.busy.to_s data-class='client'
|
6
|
+
data-type=client.type data-uuid=client.uuid
|
7
|
+
href="/clients/#{client.uuid}")
|
6
8
|
= client.busy
|
@@ -2,10 +2,14 @@ nav
|
|
2
2
|
ul#clients
|
3
3
|
- clients.each do |client|
|
4
4
|
li
|
5
|
-
a
|
6
|
-
= client.
|
5
|
+
a(data-busy=client.busy.to_s data-class='client' data-type=client.type
|
6
|
+
data-uuid=client.uuid href="/clients/#{client.uuid}")
|
7
|
+
= client.uuid
|
8
|
+
= "busy: #{client.busy.to_s}"
|
7
9
|
ul#tasks
|
8
10
|
- tasks.each do |task|
|
9
11
|
li
|
10
|
-
a data-done=task.done.to_s data-uuid=task.uuid
|
11
|
-
=
|
12
|
+
a(data-class='task' data-done=task.done.to_s data-uuid=task.uuid
|
13
|
+
href="/tasks/#{task.uuid}")
|
14
|
+
= task.uuid
|
15
|
+
= "done: #{task.done.to_s}"
|
@@ -2,8 +2,14 @@ nav
|
|
2
2
|
ul#projects
|
3
3
|
- projects.each do |project|
|
4
4
|
li
|
5
|
-
a
|
5
|
+
a(data-class='project' data-uuid=project.uuid
|
6
|
+
href="/projects/#{project.uuid}")
|
6
7
|
= project.name
|
7
8
|
|
8
9
|
form action='/projects' method='POST'
|
9
10
|
input name='name'
|
11
|
+
input name='uuid' type='hidden' value=Kamerling::UUID.new
|
12
|
+
input type='submit' value='create'
|
13
|
+
|
14
|
+
form action='/projects/dispatch' method='POST'
|
15
|
+
input type='submit' value='dispatch'
|
data/spec/kamerling/addr_spec.rb
CHANGED
@@ -1,33 +1,43 @@
|
|
1
|
+
require 'socket'
|
1
2
|
require_relative '../spec_helper'
|
3
|
+
require_relative '../../lib/kamerling/addr'
|
2
4
|
|
3
|
-
module Kamerling
|
4
|
-
|
5
|
+
module Kamerling
|
6
|
+
describe Addr do
|
7
|
+
let(:addr) { Addr['localhost', 1981, :TCP] }
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
describe '#connectable?' do
|
10
|
+
it 'is a predicate whether the (TCP) address is connectable' do
|
11
|
+
server = TCPServer.new(*addr)
|
12
|
+
addr.must_be :connectable?
|
13
|
+
server.close
|
14
|
+
addr.wont_be :connectable?
|
15
|
+
end
|
12
16
|
end
|
13
|
-
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
describe '#to_a' do
|
19
|
+
it 'returns host + port for splat use' do
|
20
|
+
splat = *addr
|
21
|
+
splat.must_equal ['localhost', 1981]
|
22
|
+
end
|
19
23
|
end
|
20
|
-
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
describe '#to_h' do
|
26
|
+
it 'returns a Hash with Integer and String values' do
|
27
|
+
addr.to_h.must_equal host: 'localhost', port: 1981, prot: 'TCP'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#to_s' do
|
32
|
+
it 'returns the Addr in URI notation' do
|
33
|
+
addr.to_s.must_equal 'tcp://localhost:1981'
|
34
|
+
end
|
25
35
|
end
|
26
|
-
end
|
27
36
|
|
28
|
-
|
29
|
-
|
30
|
-
|
37
|
+
describe '#uri' do
|
38
|
+
it 'returns and URI representation of the Addr' do
|
39
|
+
addr.uri.must_equal URI.parse('tcp://localhost:1981')
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
33
|
-
end
|
43
|
+
end
|