kamerling 0.0.1 → 0.0.2
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 -30
- data/Gemfile +1 -0
- data/Gemfile.lock +48 -16
- data/config/reek.yml +0 -4
- data/kamerling.gemspec +4 -3
- data/lib/kamerling.rb +2 -2
- data/lib/kamerling/addr.rb +4 -0
- data/lib/kamerling/client.rb +13 -1
- data/lib/kamerling/core_extensions/main.rb +2 -2
- data/lib/kamerling/handler.rb +13 -8
- data/lib/kamerling/logging.rb +22 -10
- data/lib/kamerling/message.rb +4 -4
- data/lib/kamerling/migrations/1_basic_schema.rb +3 -3
- data/lib/kamerling/net_dispatcher.rb +3 -1
- data/lib/kamerling/project.rb +2 -1
- data/lib/kamerling/registration.rb +11 -1
- data/lib/kamerling/repo.rb +1 -1
- data/lib/kamerling/result.rb +12 -1
- data/lib/kamerling/server_runner.rb +13 -15
- data/lib/kamerling/task.rb +8 -1
- data/lib/kamerling/task_dispatcher.rb +2 -2
- data/lib/kamerling/uuid_entity.rb +15 -0
- data/spec/kamerling/addr_spec.rb +6 -0
- data/spec/kamerling/handler_spec.rb +19 -8
- data/spec/kamerling/logging_spec.rb +9 -2
- data/spec/kamerling/message_spec.rb +2 -2
- data/spec/kamerling/net_dispatcher_spec.rb +2 -2
- data/spec/kamerling/receiver_spec.rb +6 -5
- data/spec/kamerling/registrar_spec.rb +9 -5
- data/spec/kamerling/repo_spec.rb +3 -3
- data/spec/kamerling/server/tcp_spec.rb +1 -1
- data/spec/kamerling/server/udp_spec.rb +1 -1
- data/spec/kamerling/server_runner_spec.rb +4 -4
- data/spec/kamerling/task_dispatcher_spec.rb +3 -3
- data/spec/kamerling/uuid_entity_spec.rb +35 -0
- data/spec/spec_helper.rb +9 -7
- metadata +24 -9
- data/lib/kamerling/uuid_object.rb +0 -79
- data/spec/kamerling/uuid_object_spec.rb +0 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9be4e3ac2863218c3d390f4afb2e80f8da0c93be
|
4
|
+
data.tar.gz: 98c18518041d91d383daa9c79c5bd46999de4b75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1b0aeb3ea6a079fd8999f326e6800edcc9f6b56ad1ab0ed997fbf71223e571ae44a7e8c02dc0f5d7d11c65e4dc98b0eae55be57e532bfd90a8d9e61030a56b6
|
7
|
+
data.tar.gz: ffe10141b36930b5bf9b4b904312ca96e62e652b51b35f1fceab122fabd7a77258cd9a137936ce6af9c48fefc5968784f189c619cb3685c53091fea66fabcde0
|
data/.rubocop.yml
CHANGED
@@ -1,27 +1,9 @@
|
|
1
1
|
AccessModifierIndentation:
|
2
2
|
Enabled: false
|
3
3
|
|
4
|
-
AlignArray:
|
5
|
-
Enabled: false
|
6
|
-
|
7
|
-
AlignHash:
|
8
|
-
Enabled: false
|
9
|
-
|
10
|
-
AlignParameters:
|
11
|
-
Enabled: false
|
12
|
-
|
13
4
|
AndOr:
|
14
5
|
Enabled: false
|
15
6
|
|
16
|
-
CaseEquality:
|
17
|
-
Enabled: false
|
18
|
-
|
19
|
-
ConstantName:
|
20
|
-
Enabled: false
|
21
|
-
|
22
|
-
CyclomaticComplexity:
|
23
|
-
Enabled: false
|
24
|
-
|
25
7
|
Documentation:
|
26
8
|
Enabled: false
|
27
9
|
|
@@ -29,22 +11,14 @@ EndAlignment:
|
|
29
11
|
Enabled: false
|
30
12
|
|
31
13
|
HandleExceptions:
|
32
|
-
|
14
|
+
Exclude:
|
15
|
+
- lib/kamerling/server/sock.rb
|
33
16
|
|
34
17
|
IndentationWidth:
|
35
18
|
Enabled: false
|
36
19
|
|
37
20
|
MethodDefParentheses:
|
38
|
-
|
39
|
-
|
40
|
-
MethodName:
|
41
|
-
Enabled: false
|
42
|
-
|
43
|
-
SignalException:
|
44
|
-
Enabled: false
|
45
|
-
|
46
|
-
SpaceAroundOperators:
|
47
|
-
Enabled: false
|
21
|
+
EnforcedStyle: require_no_parentheses
|
48
22
|
|
49
23
|
TrailingComma:
|
50
|
-
|
24
|
+
EnforcedStyleForMultiline: comma
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,34 +1,62 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/solnic/virtus.git
|
3
|
+
revision: c31940a63d1a4a2ac30032a0c01a9a217b5f5f82
|
4
|
+
specs:
|
5
|
+
virtus (1.0.2)
|
6
|
+
axiom-types (~> 0.1)
|
7
|
+
coercible (~> 1.0)
|
8
|
+
descendants_tracker (~> 0.0.3)
|
9
|
+
equalizer (~> 0.0.9)
|
10
|
+
|
1
11
|
PATH
|
2
12
|
remote: .
|
3
13
|
specs:
|
4
|
-
kamerling (0.0.
|
14
|
+
kamerling (0.0.2)
|
5
15
|
after_do (~> 0.3.0)
|
6
16
|
sequel (~> 4.4)
|
7
17
|
sinatra (~> 1.4)
|
8
18
|
slim (~> 2.0)
|
9
19
|
sqlite3 (~> 1.3)
|
20
|
+
virtus (~> 1.0)
|
10
21
|
|
11
22
|
GEM
|
12
23
|
remote: https://rubygems.org/
|
13
24
|
specs:
|
14
25
|
after_do (0.3.0)
|
15
26
|
ast (1.1.0)
|
27
|
+
atomic (1.1.16)
|
28
|
+
axiom-types (0.1.0)
|
29
|
+
descendants_tracker (~> 0.0.3)
|
30
|
+
ice_nine (~> 0.11.0)
|
31
|
+
thread_safe (~> 0.1.3)
|
16
32
|
bogus (0.1.4)
|
17
33
|
dependor (>= 0.0.4)
|
34
|
+
celluloid (0.15.2)
|
35
|
+
timers (~> 1.1.0)
|
36
|
+
celluloid-io (0.15.0)
|
37
|
+
celluloid (>= 0.15.0)
|
38
|
+
nio4r (>= 0.5.0)
|
39
|
+
coercible (1.0.0)
|
40
|
+
descendants_tracker (~> 0.0.1)
|
18
41
|
dependor (1.0.1)
|
42
|
+
descendants_tracker (0.0.3)
|
43
|
+
equalizer (0.0.9)
|
19
44
|
ffi (1.9.3)
|
45
|
+
ice_nine (0.11.0)
|
20
46
|
json (1.8.1)
|
21
|
-
listen (
|
47
|
+
listen (2.7.1)
|
48
|
+
celluloid (>= 0.15.2)
|
49
|
+
celluloid-io (>= 0.15.0)
|
22
50
|
rb-fsevent (>= 0.9.3)
|
23
51
|
rb-inotify (>= 0.9)
|
24
|
-
rb-kqueue (>= 0.2)
|
25
52
|
mini_portile (0.5.2)
|
26
|
-
minitest (5.3.
|
53
|
+
minitest (5.3.1)
|
27
54
|
minitest-focus (1.1.0)
|
28
55
|
minitest (>= 4, < 6)
|
56
|
+
nio4r (1.0.0)
|
29
57
|
nokogiri (1.6.1)
|
30
58
|
mini_portile (~> 0.5.0)
|
31
|
-
parser (2.1.
|
59
|
+
parser (2.1.7)
|
32
60
|
ast (~> 1.1)
|
33
61
|
slop (~> 3.4, >= 3.4.5)
|
34
62
|
powerpack (0.0.9)
|
@@ -42,26 +70,26 @@ GEM
|
|
42
70
|
rb-fsevent (0.9.4)
|
43
71
|
rb-inotify (0.9.3)
|
44
72
|
ffi (>= 0.5.0)
|
45
|
-
rb-kqueue (0.2.2)
|
46
|
-
ffi (>= 0.5.0)
|
47
73
|
reek (1.3.6)
|
48
74
|
ruby2ruby (~> 2.0.7)
|
49
75
|
ruby_parser (~> 3.2)
|
50
76
|
sexp_processor
|
51
|
-
rerun (0.
|
52
|
-
listen (~>
|
53
|
-
rubocop (0.
|
77
|
+
rerun (0.9.0)
|
78
|
+
listen (~> 2.7)
|
79
|
+
rubocop (0.19.1)
|
54
80
|
json (>= 1.7.7, < 2)
|
55
|
-
parser (~> 2.1.
|
81
|
+
parser (~> 2.1.7)
|
56
82
|
powerpack (~> 0.0.6)
|
57
83
|
rainbow (>= 1.99.1, < 3.0)
|
84
|
+
ruby-progressbar (~> 1.4)
|
85
|
+
ruby-progressbar (1.4.2)
|
58
86
|
ruby2ruby (2.0.7)
|
59
87
|
ruby_parser (~> 3.1)
|
60
88
|
sexp_processor (~> 4.0)
|
61
89
|
ruby_parser (3.4.1)
|
62
90
|
sexp_processor (~> 4.1)
|
63
|
-
sequel (4.
|
64
|
-
sexp_processor (4.4.
|
91
|
+
sequel (4.8.0)
|
92
|
+
sexp_processor (4.4.2)
|
65
93
|
sinatra (1.4.4)
|
66
94
|
rack (~> 1.4)
|
67
95
|
rack-protection (~> 1.4)
|
@@ -69,10 +97,13 @@ GEM
|
|
69
97
|
slim (2.0.2)
|
70
98
|
temple (~> 0.6.6)
|
71
99
|
tilt (>= 1.3.3, < 2.1)
|
72
|
-
slop (3.
|
100
|
+
slop (3.5.0)
|
73
101
|
sqlite3 (1.3.9)
|
74
102
|
temple (0.6.7)
|
103
|
+
thread_safe (0.1.3)
|
104
|
+
atomic
|
75
105
|
tilt (1.4.1)
|
106
|
+
timers (1.1.0)
|
76
107
|
|
77
108
|
PLATFORMS
|
78
109
|
ruby
|
@@ -86,5 +117,6 @@ DEPENDENCIES
|
|
86
117
|
rack-test (~> 0.6.2)
|
87
118
|
rake (~> 10.1)
|
88
119
|
reek (~> 1.3)
|
89
|
-
rerun (~> 0.
|
90
|
-
rubocop (~> 0.
|
120
|
+
rerun (~> 0.9.0)
|
121
|
+
rubocop (~> 0.19.0)
|
122
|
+
virtus!
|
data/config/reek.yml
CHANGED
data/kamerling.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.license = 'AGPL-3.0'
|
7
7
|
gem.name = 'kamerling'
|
8
8
|
gem.summary = 'Kamerling: a computation network server'
|
9
|
-
gem.version = '0.0.
|
9
|
+
gem.version = '0.0.2'
|
10
10
|
|
11
11
|
gem.files = `git ls-files -z`.split "\0"
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map { |path| File.basename path }
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.add_dependency 'sinatra', '~> 1.4'
|
18
18
|
gem.add_dependency 'slim', '~> 2.0'
|
19
19
|
gem.add_dependency 'sqlite3', '~> 1.3'
|
20
|
+
gem.add_dependency 'virtus', '~> 1.0'
|
20
21
|
|
21
22
|
gem.add_development_dependency 'bogus', '~> 0.1.3'
|
22
23
|
gem.add_development_dependency 'minitest', '~> 5.0'
|
@@ -25,6 +26,6 @@ Gem::Specification.new do |gem|
|
|
25
26
|
gem.add_development_dependency 'rack-test', '~> 0.6.2'
|
26
27
|
gem.add_development_dependency 'rake', '~> 10.1'
|
27
28
|
gem.add_development_dependency 'reek', '~> 1.3'
|
28
|
-
gem.add_development_dependency 'rerun', '~> 0.
|
29
|
-
gem.add_development_dependency 'rubocop', '~> 0.
|
29
|
+
gem.add_development_dependency 'rerun', '~> 0.9.0'
|
30
|
+
gem.add_development_dependency 'rubocop', '~> 0.19.0'
|
30
31
|
end
|
data/lib/kamerling.rb
CHANGED
@@ -20,10 +20,10 @@ require_relative 'kamerling/server/udp'
|
|
20
20
|
require_relative 'kamerling/server_runner'
|
21
21
|
require_relative 'kamerling/task_dispatcher'
|
22
22
|
require_relative 'kamerling/uuid'
|
23
|
-
require_relative 'kamerling/
|
23
|
+
require_relative 'kamerling/uuid_entity'
|
24
24
|
require_relative 'kamerling/client'
|
25
25
|
require_relative 'kamerling/project'
|
26
26
|
require_relative 'kamerling/registration'
|
27
|
-
require_relative 'kamerling/result'
|
28
27
|
require_relative 'kamerling/task'
|
28
|
+
require_relative 'kamerling/result'
|
29
29
|
require_relative 'kamerling/logging'
|
data/lib/kamerling/addr.rb
CHANGED
data/lib/kamerling/client.rb
CHANGED
@@ -1,2 +1,14 @@
|
|
1
|
-
module Kamerling class Client <
|
1
|
+
module Kamerling class Client < UUIDEntity
|
2
|
+
attribute :addr, Addr
|
3
|
+
attribute :busy, Boolean, default: false
|
4
|
+
|
5
|
+
def self.from_h hash
|
6
|
+
super.tap do |client|
|
7
|
+
client.addr = Addr[hash[:host], hash[:port], hash[:prot]]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_h
|
12
|
+
super.reject { |key, _| key == :addr }.merge addr.to_h
|
13
|
+
end
|
2
14
|
end end
|
@@ -3,8 +3,8 @@ module Kamerling module CoreExtensions module Main
|
|
3
3
|
|
4
4
|
def req param
|
5
5
|
method = caller.first[/`(.*)'$/, 1]
|
6
|
-
callsite = Class
|
7
|
-
|
6
|
+
callsite = is_a?(Class) ? "#{name}.#{method}" : "#{self.class}##{method}"
|
7
|
+
fail "#{callsite}: param #{param} is required"
|
8
8
|
end
|
9
9
|
|
10
10
|
def warn_off
|
data/lib/kamerling/handler.rb
CHANGED
@@ -6,19 +6,24 @@ module Kamerling class Handler
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def handle input, addr
|
9
|
-
|
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
|
18
|
+
|
19
|
+
def process message, addr
|
10
20
|
case message.type
|
11
21
|
when :RGST
|
12
22
|
registrar.register addr: addr, client_uuid: message.client_uuid,
|
13
|
-
|
23
|
+
project_uuid: message.project_uuid
|
14
24
|
when :RSLT
|
15
25
|
receiver.receive addr: addr, client_uuid: message.client_uuid,
|
16
|
-
|
26
|
+
data: message.payload, task_uuid: message.task_uuid
|
17
27
|
end
|
18
|
-
rescue Message::UnknownType => exception
|
19
|
-
raise UnknownInput, exception.message
|
20
28
|
end
|
21
|
-
|
22
|
-
attr_reader :receiver, :registrar
|
23
|
-
private :receiver, :registrar
|
24
29
|
end end
|
data/lib/kamerling/logging.rb
CHANGED
@@ -4,17 +4,29 @@ require 'logger'
|
|
4
4
|
module Kamerling module Logging
|
5
5
|
module_function
|
6
6
|
|
7
|
-
def log_to logger
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
def log_to logger = Logger.new($stdout)
|
8
|
+
log_dispatcher_to logger
|
9
|
+
log_server_to logger
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
private
|
14
|
+
|
15
|
+
def log_dispatcher_to logger
|
16
|
+
NetDispatcher.singleton_class.extend AfterDo
|
17
|
+
NetDispatcher.singleton_class.before :dispatch do |addr, bytes|
|
18
|
+
logger.debug "sent #{addr} #{bytes}"
|
19
|
+
end
|
15
20
|
end
|
16
|
-
|
17
|
-
|
21
|
+
|
22
|
+
def log_server_to logger
|
23
|
+
Server::Sock.extend AfterDo
|
24
|
+
Server::Sock.before(:start) { |srv| logger.info "start #{srv.addr}" }
|
25
|
+
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
|
18
30
|
end
|
19
31
|
end
|
20
32
|
end end
|
data/lib/kamerling/message.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Kamerling class Message
|
2
|
-
KnownTypes = %w[DATA PING RGST RSLT]
|
3
2
|
UnknownType = Class.new RuntimeError
|
4
3
|
|
5
|
-
def self.[]
|
6
|
-
project: req(:project), task: req(:task), type: req(:type)
|
4
|
+
def self.[] client: req(:client), payload: req(:payload),
|
5
|
+
project: req(:project), task: req(:task), type: req(:type)
|
7
6
|
new "#{type}\0\0\0\0\0\0\0\0\0\0\0\0" + UUID.bin(client.uuid) +
|
8
7
|
UUID.bin(project.uuid) + UUID.bin(task.uuid) + payload
|
9
8
|
end
|
@@ -11,7 +10,8 @@ module Kamerling class Message
|
|
11
10
|
def initialize raw
|
12
11
|
@raw = raw
|
13
12
|
type = raw[0..3]
|
14
|
-
|
13
|
+
known_types = %w(DATA PING RGST RSLT)
|
14
|
+
fail UnknownType, type unless known_types.include? type or type.empty?
|
15
15
|
end
|
16
16
|
|
17
17
|
def == other
|
@@ -19,9 +19,9 @@ Sequel.migration do
|
|
19
19
|
integer :port, null: false
|
20
20
|
string :prot, null: false
|
21
21
|
foreign_key :client_uuid, :clients, index: true, null: false,
|
22
|
-
|
22
|
+
type: :uuid
|
23
23
|
foreign_key :project_uuid, :projects, index: true, null: false,
|
24
|
-
|
24
|
+
type: :uuid
|
25
25
|
end
|
26
26
|
|
27
27
|
create_table :results do
|
@@ -39,7 +39,7 @@ Sequel.migration do
|
|
39
39
|
boolean :done, null: false
|
40
40
|
bytea :data, null: false
|
41
41
|
foreign_key :project_uuid, :projects, index: true, null: false,
|
42
|
-
|
42
|
+
type: :uuid
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
data/lib/kamerling/project.rb
CHANGED
@@ -1,2 +1,12 @@
|
|
1
|
-
module Kamerling class Registration <
|
1
|
+
module Kamerling class Registration < UUIDEntity
|
2
|
+
attribute :addr, Addr
|
3
|
+
attribute :client, Client
|
4
|
+
attribute :project, Project
|
5
|
+
|
6
|
+
def to_h
|
7
|
+
super
|
8
|
+
.reject { |key, _| key == :addr }.merge(addr.to_h)
|
9
|
+
.reject { |key, _| key == :client }.merge(client_uuid: client.uuid)
|
10
|
+
.reject { |key, _| key == :project }.merge project_uuid: project.uuid
|
11
|
+
end
|
2
12
|
end end
|
data/lib/kamerling/repo.rb
CHANGED
data/lib/kamerling/result.rb
CHANGED
@@ -1,2 +1,13 @@
|
|
1
|
-
module Kamerling class Result <
|
1
|
+
module Kamerling class Result < UUIDEntity
|
2
|
+
attribute :addr, Addr
|
3
|
+
attribute :client, Client
|
4
|
+
attribute :data, String
|
5
|
+
attribute :task, Task
|
6
|
+
|
7
|
+
def to_h
|
8
|
+
super
|
9
|
+
.reject { |key, _| key == :addr }.merge(addr.to_h)
|
10
|
+
.reject { |key, _| key == :client }.merge(client_uuid: client.uuid)
|
11
|
+
.reject { |key, _| key == :task }.merge task_uuid: task.uuid
|
12
|
+
end
|
2
13
|
end end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
|
3
3
|
module Kamerling class ServerRunner
|
4
|
-
Settings = Struct.new(*%i[db host http tcp udp])
|
5
|
-
|
6
4
|
def initialize args, classes: def_classes, orm: Sequel, repos: Repos
|
7
5
|
@args = args
|
8
6
|
repos.db = orm.connect settings.db
|
@@ -26,24 +24,24 @@ module Kamerling class ServerRunner
|
|
26
24
|
|
27
25
|
private
|
28
26
|
|
27
|
+
Settings = Struct.new(*%i(db host http tcp udp))
|
28
|
+
|
29
29
|
def def_classes
|
30
30
|
{ http: Server::HTTP, tcp: Server::TCP, udp: Server::UDP }
|
31
31
|
end
|
32
32
|
|
33
|
+
def defaults
|
34
|
+
Settings.new 'sqlite::memory:', '127.0.0.1'
|
35
|
+
end
|
36
|
+
|
33
37
|
def settings
|
34
|
-
@settings ||=
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
opts.on("--host #{sets.host}", String, 'server host') do |host|
|
42
|
-
sets.host = host
|
43
|
-
end
|
44
|
-
opts.on('--http 0', Integer, 'HTTP port') { |http| sets.http = http }
|
45
|
-
opts.on('--tcp 0', Integer, 'TCP port') { |tcp| sets.tcp = tcp }
|
46
|
-
opts.on('--udp 0', Integer, 'UDP port') { |udp| sets.udp = udp }
|
38
|
+
@settings ||= defaults.tap do |set|
|
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 }
|
47
45
|
end.parse! args
|
48
46
|
end
|
49
47
|
end
|
data/lib/kamerling/task.rb
CHANGED
@@ -1,2 +1,9 @@
|
|
1
|
-
module Kamerling class Task <
|
1
|
+
module Kamerling class Task < UUIDEntity
|
2
|
+
attribute :data, String
|
3
|
+
attribute :done, Boolean, default: false
|
4
|
+
attribute :project, Project
|
5
|
+
|
6
|
+
def to_h
|
7
|
+
super.reject { |key, _| key == :project }.merge project_uuid: project.uuid
|
8
|
+
end
|
2
9
|
end end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Kamerling class TaskDispatcher
|
2
|
-
def initialize net_dispatcher: NetDispatcher
|
2
|
+
def initialize net_dispatcher: NetDispatcher, repos: Repos
|
3
3
|
@net_dispatcher = net_dispatcher
|
4
4
|
@repos = repos
|
5
5
|
end
|
@@ -21,7 +21,7 @@ module Kamerling class TaskDispatcher
|
|
21
21
|
def dispatch_task client: req(:client), project: req(:project),
|
22
22
|
task: req(:task)
|
23
23
|
message = Message[client: client, payload: task.data, project: project,
|
24
|
-
|
24
|
+
task: task, type: :DATA]
|
25
25
|
net_dispatcher.dispatch client.addr, message.to_s
|
26
26
|
client.busy = true
|
27
27
|
repos << client
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
|
3
|
+
module Kamerling class UUIDEntity
|
4
|
+
include Equalizer.new :uuid
|
5
|
+
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
attribute :uuid, String, default: -> * { UUID.new }
|
9
|
+
|
10
|
+
class << self
|
11
|
+
alias_method :from_h, :new
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :to_h, :attributes
|
15
|
+
end end
|
data/spec/kamerling/addr_spec.rb
CHANGED
@@ -19,6 +19,12 @@ module Kamerling describe Addr do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
describe '#to_h' do
|
23
|
+
it 'returns a Hash with Integer and String values' do
|
24
|
+
addr.to_h.must_equal host: 'localhost', port: 1981, prot: 'TCP'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
22
28
|
describe '#to_s' do
|
23
29
|
it 'returns the Addr in ‘host:port (protocol)’ notation' do
|
24
30
|
addr.to_s.must_equal 'localhost:1981 (TCP)'
|
@@ -7,19 +7,30 @@ module Kamerling describe Handler do
|
|
7
7
|
|
8
8
|
it 'handles RGST inputs' do
|
9
9
|
input = 'RGST' + "\0" * 12 + '16B client UUID16B project UUID'
|
10
|
+
client_uuid = UUID['16B client UUID']
|
11
|
+
project_uuid = UUID['16B project UUID']
|
10
12
|
handler.handle input, addr
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
args = {
|
14
|
+
addr: addr,
|
15
|
+
client_uuid: client_uuid,
|
16
|
+
project_uuid: project_uuid,
|
17
|
+
}
|
18
|
+
registrar.must_have_received :register, [args]
|
14
19
|
end
|
15
20
|
|
16
21
|
it 'handles RSLT inputs' do
|
17
|
-
input = 'RSLT' + "\0" * 12
|
18
|
-
|
22
|
+
input = 'RSLT' + "\0" * 12 +
|
23
|
+
'16B client UUID16B project UUID16B task UUIDdata'
|
24
|
+
client_uuid = UUID['16B client UUID']
|
25
|
+
task_uuid = UUID['16B task UUID']
|
19
26
|
handler.handle input, addr
|
20
|
-
|
21
|
-
|
22
|
-
|
27
|
+
args = {
|
28
|
+
addr: addr,
|
29
|
+
client_uuid: client_uuid,
|
30
|
+
data: 'data',
|
31
|
+
task_uuid: task_uuid,
|
32
|
+
}
|
33
|
+
receiver.must_have_received :receive, [args]
|
23
34
|
end
|
24
35
|
|
25
36
|
it 'raises on unknown inputs' do
|
@@ -8,7 +8,7 @@ module Kamerling describe Logging do
|
|
8
8
|
let(:udp_server) { Server::UDP.new addr: Addr['localhost', 1979, :UDP] }
|
9
9
|
|
10
10
|
before do
|
11
|
-
Logging.log_to logger
|
11
|
+
Logging.log_to logger
|
12
12
|
tcp_server.start
|
13
13
|
udp_server.start
|
14
14
|
end
|
@@ -18,7 +18,7 @@ module Kamerling describe Logging do
|
|
18
18
|
udp_server.stop
|
19
19
|
end
|
20
20
|
|
21
|
-
describe '.
|
21
|
+
describe '.log_to' do
|
22
22
|
it 'logs TCP server starts' do
|
23
23
|
logged.must_include 'start localhost:1981 (TCP)'
|
24
24
|
end
|
@@ -69,5 +69,12 @@ module Kamerling describe Logging do
|
|
69
69
|
run_all_threads
|
70
70
|
logged.must_include "received #{udp_addr} PING"
|
71
71
|
end
|
72
|
+
|
73
|
+
it 'logs packet dispatches' do
|
74
|
+
server = UDPSocket.new.tap { |s| s.bind '127.0.0.1', 0 }
|
75
|
+
addr = Addr[server.addr[3], server.addr[1], :UDP]
|
76
|
+
NetDispatcher.dispatch addr, 'PING'
|
77
|
+
logged.must_include "sent #{addr} PING"
|
78
|
+
end
|
72
79
|
end
|
73
80
|
end end
|
@@ -12,7 +12,7 @@ module Kamerling describe Message do
|
|
12
12
|
project = fake :project, uuid: UUID.new
|
13
13
|
task = fake :task, uuid: UUID.new
|
14
14
|
message = Message[client: client, payload: 'pay', project: project,
|
15
|
-
|
15
|
+
task: task, type: :DATA]
|
16
16
|
message.client_uuid.must_equal client.uuid
|
17
17
|
message.project_uuid.must_equal project.uuid
|
18
18
|
message.task_uuid.must_equal task.uuid
|
@@ -57,7 +57,7 @@ module Kamerling describe Message do
|
|
57
57
|
|
58
58
|
describe '#to_s' do
|
59
59
|
it 'returns the raw bytes' do
|
60
|
-
mess.to_s.must_equal "#{mess.type}\0\0\0\0\0\0\0\0\0\0\0\0"
|
60
|
+
mess.to_s.must_equal "#{mess.type}\0\0\0\0\0\0\0\0\0\0\0\0" \
|
61
61
|
'16B client UUID16B project UUID16B task UUIDsome payload'
|
62
62
|
end
|
63
63
|
end
|
@@ -6,7 +6,7 @@ module Kamerling describe NetDispatcher do
|
|
6
6
|
server = TCPServer.open 0
|
7
7
|
thread = Thread.new { server.accept.read }
|
8
8
|
addr = Addr[server.addr[3], server.addr[1], :TCP]
|
9
|
-
NetDispatcher.
|
9
|
+
NetDispatcher.dispatch addr, 'foo'
|
10
10
|
thread.value.must_equal 'foo'
|
11
11
|
end
|
12
12
|
|
@@ -14,7 +14,7 @@ module Kamerling describe NetDispatcher do
|
|
14
14
|
server = UDPSocket.new.tap { |s| s.bind '127.0.0.1', 0 }
|
15
15
|
thread = Thread.new { server.recvfrom(2**16).first }
|
16
16
|
addr = Addr[server.addr[3], server.addr[1], :UDP]
|
17
|
-
NetDispatcher.
|
17
|
+
NetDispatcher.dispatch addr, 'foo'
|
18
18
|
thread.value.must_equal 'foo'
|
19
19
|
end
|
20
20
|
end
|
@@ -10,13 +10,14 @@ module Kamerling describe Receiver do
|
|
10
10
|
stub(repos).[](Client) { fake :repo, :[] => client }
|
11
11
|
stub(repos).[](Task) { fake :repo, :[] => task }
|
12
12
|
Receiver.new.receive addr: addr, client_uuid: client.uuid, data: 'data',
|
13
|
-
|
13
|
+
repos: repos, task_uuid: task.uuid
|
14
|
+
result = Result.new addr: addr, client: client, data: 'data', task: task,
|
15
|
+
uuid: anything
|
14
16
|
client.must_have_received :busy=, [false]
|
15
17
|
task.must_have_received :done=, [true]
|
16
|
-
repos.must_have_received
|
17
|
-
repos.must_have_received
|
18
|
-
repos.must_have_received
|
19
|
-
data: 'data', task: task, uuid: anything)]
|
18
|
+
repos.must_have_received :<<, [client]
|
19
|
+
repos.must_have_received :<<, [task]
|
20
|
+
repos.must_have_received :<<, [result]
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end end
|
@@ -5,12 +5,16 @@ module Kamerling describe Registrar do
|
|
5
5
|
fakes :addr, :client, :project, :repo
|
6
6
|
|
7
7
|
it 'registers that the given client can do the given project' do
|
8
|
-
repos = {
|
9
|
-
|
8
|
+
repos = {
|
9
|
+
Client => { client.uuid => client },
|
10
|
+
Project => { project.uuid => project },
|
11
|
+
Registration => repo,
|
12
|
+
}
|
10
13
|
Registrar.new.register addr: addr, client_uuid: client.uuid,
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
project_uuid: project.uuid, repos: repos
|
15
|
+
registration = Registration.new addr: addr, client: client,
|
16
|
+
project: project, uuid: anything
|
17
|
+
repo.must_have_received :<<, [registration]
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end end
|
data/spec/kamerling/repo_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
3
|
module Kamerling describe Repo do
|
4
|
-
Tune =
|
4
|
+
Tune = Class.new(UUIDEntity) { attribute :genre, Symbol }
|
5
5
|
|
6
6
|
describe '#<<' do
|
7
7
|
it 'passes the Hash version of an object to the source' do
|
@@ -15,7 +15,7 @@ module Kamerling describe Repo do
|
|
15
15
|
dataset = fake Sequel::Dataset
|
16
16
|
source = fake Sequel::Dataset
|
17
17
|
tune = Tune.new genre: :chap_hop
|
18
|
-
stub(source).<<(tune.to_h) {
|
18
|
+
stub(source).<<(tune.to_h) { fail Sequel::UniqueConstraintViolation }
|
19
19
|
stub(source).where(uuid: tune.uuid) { dataset }
|
20
20
|
Repo.new(Tune, source) << tune
|
21
21
|
dataset.must_have_received :update, [tune.to_h]
|
@@ -39,7 +39,7 @@ module Kamerling describe Repo do
|
|
39
39
|
it 'returns all objects' do
|
40
40
|
tune = Tune.new genre: :chap_hop, uuid: UUID.new
|
41
41
|
source = fake Sequel::Dataset,
|
42
|
-
|
42
|
+
all: [{ genre: :chap_hop, uuid: tune.uuid }]
|
43
43
|
Repo.new(Tune, source).all.must_equal [tune]
|
44
44
|
end
|
45
45
|
end
|
@@ -30,7 +30,7 @@ module Kamerling describe Server::TCP do
|
|
30
30
|
it 'doesn’t blow up on unknown inputs' do
|
31
31
|
server = Server::TCP.new addr: addr, handler: handler = fake(:handler)
|
32
32
|
server.start
|
33
|
-
stub(handler).handle('foo', any(Addr)) {
|
33
|
+
stub(handler).handle('foo', any(Addr)) { fail Handler::UnknownInput }
|
34
34
|
TCPSocket.open(*server.addr) { |socket| socket << 'foo' }
|
35
35
|
server.stop
|
36
36
|
end
|
@@ -22,7 +22,7 @@ module Kamerling describe Server::UDP do
|
|
22
22
|
it 'doesn’t blow up on unknown inputs' do
|
23
23
|
server = Server::UDP.new addr: addr, handler: handler = fake(:handler)
|
24
24
|
server.start
|
25
|
-
stub(handler).handle('foo', any(Addr)) {
|
25
|
+
stub(handler).handle('foo', any(Addr)) { fail Handler::UnknownInput }
|
26
26
|
UDPSocket.new.send 'foo', 0, *server.addr
|
27
27
|
run_all_threads
|
28
28
|
server.stop
|
@@ -20,7 +20,7 @@ module Kamerling describe ServerRunner do
|
|
20
20
|
|
21
21
|
describe '.new' do
|
22
22
|
it 'hooks to the given database' do
|
23
|
-
args = %w
|
23
|
+
args = %w(--host 0.0.0.0 --db sqlite::memory:)
|
24
24
|
db = fake { Sequel::SQLite::Database }
|
25
25
|
orm = fake :sequel, as: :class
|
26
26
|
stub(orm).connect('sqlite::memory:') { db }
|
@@ -32,7 +32,7 @@ module Kamerling describe ServerRunner do
|
|
32
32
|
|
33
33
|
describe '#join' do
|
34
34
|
it 'joins all the created servers' do
|
35
|
-
args = %w
|
35
|
+
args = %w(--host 0.0.0.0 --http 1234)
|
36
36
|
ServerRunner.new(args, classes: classes).join
|
37
37
|
http.must_have_received :join, []
|
38
38
|
tcp.wont_have_received :join, []
|
@@ -42,7 +42,7 @@ module Kamerling describe ServerRunner do
|
|
42
42
|
|
43
43
|
describe '#start' do
|
44
44
|
it 'starts the servers based on the given command-line parameters' do
|
45
|
-
args = %w
|
45
|
+
args = %w(--host 0.0.0.0 --http 1234 --tcp 3456 --udp 5678)
|
46
46
|
ServerRunner.new(args, classes: classes).start
|
47
47
|
http.must_have_received :start, []
|
48
48
|
tcp.must_have_received :start, []
|
@@ -50,7 +50,7 @@ module Kamerling describe ServerRunner do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'starts only the servers for which the port was given' do
|
53
|
-
args = %w
|
53
|
+
args = %w(--host 0.0.0.0 --http 1234)
|
54
54
|
ServerRunner.new(args, classes: classes).start
|
55
55
|
http.must_have_received :start, []
|
56
56
|
tcp.wont_have_received :start, []
|
@@ -10,12 +10,12 @@ module Kamerling describe TaskDispatcher do
|
|
10
10
|
repos = fake :repos, as: :class, projects: [project]
|
11
11
|
stub(repos).next_task_for(project) { task }
|
12
12
|
stub(repos).free_clients_for(project) { [client] }
|
13
|
-
net_dispatcher = fake :net_dispatcher
|
13
|
+
net_dispatcher = fake :net_dispatcher, as: :class
|
14
14
|
|
15
15
|
TaskDispatcher.new(net_dispatcher: net_dispatcher, repos: repos).dispatch
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
header = "DATA#{"\0" * 12}16B client UUID16B project UUID16B task "
|
18
|
+
net_dispatcher.must_have_received :dispatch, [addr, header + 'UUIDdata']
|
19
19
|
client.must_have_received :busy=, [true]
|
20
20
|
repos.must_have_received :<<, [client]
|
21
21
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module Kamerling describe UUIDEntity do
|
4
|
+
describe '.from_h' do
|
5
|
+
it 'deserialises the object from a Hash' do
|
6
|
+
Trivial = Class.new(UUIDEntity) { attribute :question, Symbol }
|
7
|
+
Trivial.from_h(question: :answer).question.must_equal :answer
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
it 'creates a class with an UUID property defaulting to a random UUID' do
|
13
|
+
AttrLess = Class.new UUIDEntity
|
14
|
+
AttrLess.new.uuid.must_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/)
|
15
|
+
AttrLess.new.uuid.wont_equal AttrLess.new.uuid
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#==' do
|
20
|
+
it 'reports UUID-based euqality' do
|
21
|
+
Actor = Class.new(UUIDEntity) { attribute :name, Symbol }
|
22
|
+
Actor.new(name: :laurel).wont_equal Actor.new name: :laurel
|
23
|
+
uuid = UUID.new
|
24
|
+
Actor.new(name: :laurel, uuid: uuid)
|
25
|
+
.must_equal Actor.new name: :hardy, uuid: uuid
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#to_h' do
|
30
|
+
it 'serialises the object to a Hash' do
|
31
|
+
Hashble = Class.new(UUIDEntity) { attribute :param, Symbol }
|
32
|
+
Hashble.new(param: :val).to_h.must_equal param: :val, uuid: any(String)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,14 +9,16 @@ require 'kamerling'
|
|
9
9
|
|
10
10
|
Bogus.configure { |config| config.search_modules << Kamerling }
|
11
11
|
|
12
|
-
module
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
12
|
+
module Minitest
|
13
|
+
class Spec
|
14
|
+
include Rack::Test::Methods
|
17
15
|
|
18
|
-
|
19
|
-
|
16
|
+
module DSL
|
17
|
+
def fakes *args
|
18
|
+
args.map { |arg| fake arg }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
Thread.abort_on_exception = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kamerling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Szotkowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: after_do
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: virtus
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: bogus
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,28 +198,28 @@ dependencies:
|
|
184
198
|
requirements:
|
185
199
|
- - "~>"
|
186
200
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.
|
201
|
+
version: 0.9.0
|
188
202
|
type: :development
|
189
203
|
prerelease: false
|
190
204
|
version_requirements: !ruby/object:Gem::Requirement
|
191
205
|
requirements:
|
192
206
|
- - "~>"
|
193
207
|
- !ruby/object:Gem::Version
|
194
|
-
version: 0.
|
208
|
+
version: 0.9.0
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
210
|
name: rubocop
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
198
212
|
requirements:
|
199
213
|
- - "~>"
|
200
214
|
- !ruby/object:Gem::Version
|
201
|
-
version: 0.
|
215
|
+
version: 0.19.0
|
202
216
|
type: :development
|
203
217
|
prerelease: false
|
204
218
|
version_requirements: !ruby/object:Gem::Requirement
|
205
219
|
requirements:
|
206
220
|
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
|
-
version: 0.
|
222
|
+
version: 0.19.0
|
209
223
|
description: A network server for distributing computations across different clients
|
210
224
|
speaking TCP or UDP.
|
211
225
|
email: p.szotkowski@tele.pw.edu.pl
|
@@ -250,7 +264,7 @@ files:
|
|
250
264
|
- lib/kamerling/task.rb
|
251
265
|
- lib/kamerling/task_dispatcher.rb
|
252
266
|
- lib/kamerling/uuid.rb
|
253
|
-
- lib/kamerling/
|
267
|
+
- lib/kamerling/uuid_entity.rb
|
254
268
|
- lib/kamerling/views/clients.slim
|
255
269
|
- lib/kamerling/views/layout.slim
|
256
270
|
- lib/kamerling/views/project.slim
|
@@ -274,7 +288,7 @@ files:
|
|
274
288
|
- spec/kamerling/server_runner_spec.rb
|
275
289
|
- spec/kamerling/task_dispatcher_spec.rb
|
276
290
|
- spec/kamerling/task_spec.rb
|
277
|
-
- spec/kamerling/
|
291
|
+
- spec/kamerling/uuid_entity_spec.rb
|
278
292
|
- spec/kamerling/uuid_spec.rb
|
279
293
|
- spec/spec_helper.rb
|
280
294
|
homepage: https://github.com/chastell/kamerling
|
@@ -320,6 +334,7 @@ test_files:
|
|
320
334
|
- spec/kamerling/server_runner_spec.rb
|
321
335
|
- spec/kamerling/task_dispatcher_spec.rb
|
322
336
|
- spec/kamerling/task_spec.rb
|
323
|
-
- spec/kamerling/
|
337
|
+
- spec/kamerling/uuid_entity_spec.rb
|
324
338
|
- spec/kamerling/uuid_spec.rb
|
325
339
|
- spec/spec_helper.rb
|
340
|
+
has_rdoc:
|
@@ -1,79 +0,0 @@
|
|
1
|
-
module Kamerling
|
2
|
-
def self.UUIDObject *params
|
3
|
-
class_definition_from attrs_from params
|
4
|
-
end
|
5
|
-
|
6
|
-
private
|
7
|
-
|
8
|
-
def self.attrs_from params
|
9
|
-
{ uuid: -> { UUID.new } }.tap do |attrs|
|
10
|
-
attrs.merge! params.pop if params.last.is_a? Hash
|
11
|
-
attrs.merge! raises_from params
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.class_definition_from attrs
|
16
|
-
Class.new do
|
17
|
-
define_singleton_method(:attrs) { attrs }
|
18
|
-
|
19
|
-
def self.from_h hash, repos: Repos
|
20
|
-
args = hash.reduce({}) do |result, (key, _)|
|
21
|
-
result.merge from_h_mapping hash, key, repos
|
22
|
-
end
|
23
|
-
new args
|
24
|
-
end
|
25
|
-
|
26
|
-
def initialize args = {}
|
27
|
-
@values = Hash[self.class.attrs.map do |attr, default|
|
28
|
-
value = args.fetch attr do
|
29
|
-
default.respond_to?(:call) ? default.call : default
|
30
|
-
end
|
31
|
-
[attr, value]
|
32
|
-
end]
|
33
|
-
end
|
34
|
-
|
35
|
-
def == other
|
36
|
-
uuid == other.uuid
|
37
|
-
end
|
38
|
-
|
39
|
-
attrs.each do |attr, _|
|
40
|
-
define_method(attr) { @values[attr] }
|
41
|
-
define_method("#{attr}=") { |val| @values[attr] = val }
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_h
|
45
|
-
self.class.attrs.reduce({}) do |hash, (attr, _)|
|
46
|
-
hash.merge to_h_mapping attr
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def self.from_h_mapping hash, key, repos
|
53
|
-
case key
|
54
|
-
when :host, :port, :prot
|
55
|
-
{ addr: Addr[hash[:host], hash[:port], hash[:prot].to_sym] }
|
56
|
-
when :client_uuid then { client: repos[Client][hash[key]] }
|
57
|
-
when :project_uuid then { project: repos[Project][hash[key]] }
|
58
|
-
when :task_uuid then { task: repos[Task][hash[key]] }
|
59
|
-
else { key => hash[key] }
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_h_mapping attr
|
64
|
-
case value = @values[attr]
|
65
|
-
when Addr
|
66
|
-
{ host: value.host, port: value.port, prot: value.prot.to_s }
|
67
|
-
when Client then { client_uuid: client.uuid }
|
68
|
-
when Project then { project_uuid: project.uuid }
|
69
|
-
when Task then { task_uuid: task.uuid }
|
70
|
-
else { attr => value }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.raises_from params
|
77
|
-
Hash[params.map { |param| [param, -> { raise "#{param} required" }] }]
|
78
|
-
end
|
79
|
-
end
|
@@ -1,101 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
module Kamerling describe '.UUIDObject' do
|
4
|
-
describe '.from_h' do
|
5
|
-
it 'deserialises the object from a Hash' do
|
6
|
-
Trivial = Kamerling.UUIDObject :question
|
7
|
-
Trivial.from_h(question: :answer).question.must_equal :answer
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'deserialises addr' do
|
11
|
-
Netable = Kamerling.UUIDObject :addr
|
12
|
-
Netable.from_h(host: '127.0.0.1', port: 1981, prot: :TCP).addr
|
13
|
-
.must_equal Addr['127.0.0.1', 1981, :TCP]
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'deserialises {client,project,task}_uuid' do
|
17
|
-
client = fake :client, uuid: UUID.new
|
18
|
-
project = fake :project, uuid: UUID.new
|
19
|
-
task = fake :task, uuid: UUID.new
|
20
|
-
Complete = Kamerling.UUIDObject :client, :project, :task
|
21
|
-
repos = {
|
22
|
-
Client => { client.uuid => client },
|
23
|
-
Project => { project.uuid => project },
|
24
|
-
Task => { task.uuid => task },
|
25
|
-
}
|
26
|
-
hash = { client_uuid: client.uuid, project_uuid: project.uuid,
|
27
|
-
task_uuid: task.uuid, uuid: UUID.new }
|
28
|
-
complete = Complete.from_h hash, repos: repos
|
29
|
-
complete.client.must_equal client
|
30
|
-
complete.project.must_equal project
|
31
|
-
complete.task.must_equal task
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe '.new' do
|
36
|
-
it 'creates a class with an UUID property defaulting to a random UUID' do
|
37
|
-
AttrLess = Kamerling.UUIDObject
|
38
|
-
AttrLess.new.uuid.must_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/)
|
39
|
-
AttrLess.new.uuid.wont_equal AttrLess.new.uuid
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'allows setting custom properties and raises when they lack defaults' do
|
43
|
-
FooFul = Kamerling.UUIDObject :foo
|
44
|
-
FooFul.new(foo: 'bar').foo.must_equal 'bar'
|
45
|
-
-> { FooFul.new }.must_raise RuntimeError
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'allows setting properties’ default procs' do
|
49
|
-
ProcFul = Kamerling.UUIDObject rand: -> { rand }
|
50
|
-
ProcFul.new.rand.wont_equal ProcFul.new.rand
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'allows setting properties’ default values' do
|
54
|
-
ValFul = Kamerling.UUIDObject bar: :baz
|
55
|
-
ValFul.new.bar.must_equal :baz
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '#==' do
|
60
|
-
it 'reports UUID-based euqality' do
|
61
|
-
Actor = Kamerling.UUIDObject :name
|
62
|
-
Actor.new(name: :laurel).wont_equal Actor.new name: :laurel
|
63
|
-
uuid = UUID.new
|
64
|
-
Actor.new(name: :laurel, uuid: uuid)
|
65
|
-
.must_equal Actor.new name: :hardy, uuid: uuid
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe '#to_h' do
|
70
|
-
it 'serialises the object to a Hash' do
|
71
|
-
Hashble = Kamerling.UUIDObject :param
|
72
|
-
Hashble.new(param: :val).to_h.must_equal param: :val, uuid: anything
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'serialises addr' do
|
76
|
-
Addrble = Kamerling.UUIDObject :addr
|
77
|
-
addrble = Addrble.new addr: Addr['127.0.0.1', 1981, :TCP]
|
78
|
-
addrble.to_h.must_equal host: '127.0.0.1', port: 1981, prot: 'TCP',
|
79
|
-
uuid: anything
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'serialises client' do
|
83
|
-
Clintable = Kamerling.UUIDObject :client
|
84
|
-
clintable = Clintable.new client: client = Client.new(addr: fake(:addr))
|
85
|
-
clintable.to_h.must_equal client_uuid: client.uuid, uuid: anything
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'serialises project' do
|
89
|
-
Projable = Kamerling.UUIDObject :project
|
90
|
-
projable = Projable.new project: project = Project.new(name: 'name')
|
91
|
-
projable.to_h.must_equal project_uuid: project.uuid, uuid: anything
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'serialises task' do
|
95
|
-
project = fake :project
|
96
|
-
Tskble = Kamerling.UUIDObject :task
|
97
|
-
tskble = Tskble.new task: task = Task.new(data: 'data', project: project)
|
98
|
-
tskble.to_h.must_equal task_uuid: task.uuid, uuid: anything
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end end
|