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
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require_relative '../../lib/kamerling/registration'
|
3
|
+
|
4
|
+
module Kamerling
|
5
|
+
describe Registration do
|
6
|
+
describe '#registered_at' do
|
7
|
+
it 'defaults to the current time' do
|
8
|
+
registered_at = Registration.new.registered_at
|
9
|
+
assert registered_at.between?(Time.now - 1, Time.now + 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'defaults to the time of Registration’s creation' do
|
13
|
+
Registration.new.registered_at.wont_equal Registration.new.registered_at
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/kamerling/repo_spec.rb
CHANGED
@@ -1,60 +1,76 @@
|
|
1
|
+
require 'sequel'
|
1
2
|
require_relative '../spec_helper'
|
3
|
+
require_relative '../../lib/kamerling/mapper'
|
4
|
+
require_relative '../../lib/kamerling/project'
|
5
|
+
require_relative '../../lib/kamerling/repo'
|
6
|
+
require_relative '../../lib/kamerling/uuid'
|
7
|
+
require_relative '../../lib/kamerling/uuid_entity'
|
2
8
|
|
3
|
-
module Kamerling
|
4
|
-
|
9
|
+
module Kamerling
|
10
|
+
describe Repo do
|
11
|
+
Tune = Class.new(UUIDEntity) { attrs genre: Symbol }
|
5
12
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
describe '#<<' do
|
14
|
+
it 'passes the Hash version of an object to the source via a mapper' do
|
15
|
+
tune = Tune.new(genre: :chap_hop)
|
16
|
+
source = fake(Sequel::Dataset)
|
17
|
+
Repo.new(Tune, source) << tune
|
18
|
+
source.must_have_received :<<, [tune.to_h]
|
19
|
+
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
it 'updates the source’s version if it exists there' do
|
22
|
+
dataset = fake(Sequel::Dataset)
|
23
|
+
source = fake(Sequel::Dataset)
|
24
|
+
tune = Tune.new(genre: :chap_hop)
|
25
|
+
stub(source).<<(tune.to_h) { fail Sequel::UniqueConstraintViolation }
|
26
|
+
stub(source).where(uuid: tune.uuid) { dataset }
|
27
|
+
Repo.new(Tune, source) << tune
|
28
|
+
dataset.must_have_received :update, [tune.to_h]
|
29
|
+
end
|
22
30
|
end
|
23
|
-
end
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
describe '#[]' do
|
33
|
+
it 'hydrates the object found in the repo via a mapper' do
|
34
|
+
tune = Tune.new(genre: :chap_hop)
|
35
|
+
hash = { genre: :chap_hop, uuid: tune.uuid }
|
36
|
+
source = { { uuid: tune.uuid } => hash }
|
37
|
+
mapper = fake(:mapper, as: :class)
|
38
|
+
stub(mapper).from_h(Tune, hash) { tune }
|
39
|
+
retrieved = Repo.new(Tune, source, mapper: mapper)[tune.uuid]
|
40
|
+
retrieved.to_h.must_equal tune.to_h
|
41
|
+
end
|
32
42
|
|
33
|
-
|
34
|
-
|
43
|
+
it 'raises NotFound if the object is not found in the repo' do
|
44
|
+
-> { Repo.new(Tune, {})[UUID.new] }.must_raise Repo::NotFound
|
45
|
+
end
|
35
46
|
end
|
36
|
-
end
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
describe '#all' do
|
49
|
+
it 'returns all objects via a mapper' do
|
50
|
+
tune = Tune.new(genre: :chap_hop)
|
51
|
+
source = fake(Sequel::Dataset, all: [genre: :chap_hop, uuid: tune.uuid])
|
52
|
+
mapper = fake(:mapper, as: :class, from_h: tune)
|
53
|
+
Repo.new(Tune, source, mapper: mapper).all.must_equal [tune]
|
54
|
+
end
|
44
55
|
end
|
45
|
-
end
|
46
56
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
describe '#related_to' do
|
58
|
+
it 'returns objects related to the given object via a mapper' do
|
59
|
+
ragga = Tune.new(genre: :ragga)
|
60
|
+
reggae = Tune.new(genre: :reggae)
|
61
|
+
project = Project.new
|
62
|
+
results = [
|
63
|
+
{ genre: :ragga, uuid: ragga.uuid },
|
64
|
+
{ genre: :reggae, uuid: reggae.uuid },
|
65
|
+
]
|
66
|
+
source = fake(Sequel::Dataset)
|
67
|
+
stub(source).where(project_uuid: project.uuid) { results }
|
68
|
+
mapper = fake(:mapper, as: :class)
|
69
|
+
stub(mapper).from_h(Tune, genre: :ragga, uuid: ragga.uuid) { ragga }
|
70
|
+
stub(mapper).from_h(Tune, genre: :reggae, uuid: reggae.uuid) { reggae }
|
71
|
+
repo = Repo.new(Tune, source, mapper: mapper)
|
72
|
+
repo.related_to(project).must_equal [ragga, reggae]
|
73
|
+
end
|
58
74
|
end
|
59
75
|
end
|
60
|
-
end
|
76
|
+
end
|
@@ -1,136 +1,148 @@
|
|
1
|
+
require 'sequel'
|
1
2
|
require_relative '../spec_helper'
|
3
|
+
require_relative '../../lib/kamerling/addr'
|
4
|
+
require_relative '../../lib/kamerling/client'
|
5
|
+
require_relative '../../lib/kamerling/project'
|
6
|
+
require_relative '../../lib/kamerling/registration'
|
7
|
+
require_relative '../../lib/kamerling/repo'
|
8
|
+
require_relative '../../lib/kamerling/repos'
|
9
|
+
require_relative '../../lib/kamerling/result'
|
10
|
+
require_relative '../../lib/kamerling/task'
|
11
|
+
require_relative '../../lib/kamerling/uuid'
|
2
12
|
|
3
|
-
module Kamerling
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
13
|
+
module Kamerling
|
14
|
+
describe Repos do
|
15
|
+
describe '.<<' do
|
16
|
+
it 'shuffles the object into the right repo' do
|
17
|
+
Repos.repos = { Object => repo = fake(:repo) }
|
18
|
+
Repos.<< object = Object.new
|
19
|
+
repo.must_have_received :<<, [object]
|
20
|
+
end
|
10
21
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
22
|
+
it 'can be chained' do
|
23
|
+
str_repo, sym_repo = fake(:repo), fake(:repo)
|
24
|
+
Repos.repos = { String => str_repo, Symbol => sym_repo }
|
25
|
+
Repos << 'str' << :sym
|
26
|
+
str_repo.must_have_received :<<, ['str']
|
27
|
+
sym_repo.must_have_received :<<, [:sym]
|
28
|
+
end
|
17
29
|
end
|
18
|
-
end
|
19
30
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
31
|
+
describe '.[]' do
|
32
|
+
it 'allows querying for repository objects' do
|
33
|
+
client = Client.new
|
34
|
+
Repos.repos = { Client => {} }
|
35
|
+
Repos[Client][client.uuid].must_be_nil
|
36
|
+
Repos.repos = { Client => { client.uuid => client } }
|
37
|
+
Repos[Client][client.uuid].must_equal client
|
38
|
+
end
|
27
39
|
end
|
28
|
-
end
|
29
40
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
41
|
+
describe '.clients' do
|
42
|
+
it 'returns all clients' do
|
43
|
+
Repos.repos = { Client => fake(:repo, all: all_clients = fake) }
|
44
|
+
Repos.clients.must_equal all_clients
|
45
|
+
end
|
34
46
|
end
|
35
|
-
end
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
48
|
+
describe '.clients_for' do
|
49
|
+
it 'returns all clients for the given project' do
|
50
|
+
clients = [Client.new, Client.new]
|
51
|
+
project = Project.new
|
52
|
+
regs = clients.map { |client| Registration.new(client: client) }
|
53
|
+
reg_repo = fake(:repo)
|
54
|
+
stub(reg_repo).related_to(project) { regs }
|
55
|
+
Repos.repos = { Registration => reg_repo }
|
56
|
+
Repos.clients_for(project).must_equal clients
|
57
|
+
end
|
46
58
|
end
|
47
|
-
end
|
48
59
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
describe '.db=' do
|
61
|
+
it 'auto-migrates the passed db' do
|
62
|
+
db = Sequel.sqlite
|
63
|
+
warn_off { db.tables.wont_include :schema_info }
|
64
|
+
Repos.db = db
|
65
|
+
warn_off { db.tables.must_include :schema_info }
|
66
|
+
end
|
55
67
|
end
|
56
|
-
end
|
57
68
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
+
describe '.free_clients_for' do
|
70
|
+
it 'returns free clients for the given project' do
|
71
|
+
busy_client = Client.new(busy: true)
|
72
|
+
free_client = Client.new(busy: false)
|
73
|
+
busy_reg = Registration.new(client: busy_client)
|
74
|
+
free_reg = Registration.new(client: free_client)
|
75
|
+
project = Project.new
|
76
|
+
repo = fake(:repo)
|
77
|
+
stub(repo).related_to(project) { [busy_reg, free_reg] }
|
78
|
+
Repos.repos = { Registration => repo }
|
79
|
+
Repos.free_clients_for(project).must_equal [free_client]
|
80
|
+
end
|
69
81
|
end
|
70
|
-
end
|
71
82
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
83
|
+
describe '.next_task_for' do
|
84
|
+
it 'returns the next task for the given project' do
|
85
|
+
project = Project.new
|
86
|
+
done_task = Task.new(done: true)
|
87
|
+
new_task = Task.new(done: false)
|
88
|
+
repo = fake(:repo)
|
89
|
+
stub(repo).related_to(project) { [done_task, new_task] }
|
90
|
+
Repos.repos = { Task => repo }
|
91
|
+
Repos.next_task_for(project).must_equal new_task
|
92
|
+
end
|
81
93
|
end
|
82
|
-
end
|
83
94
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
95
|
+
describe '.project' do
|
96
|
+
it 'returns the project with the given UUID' do
|
97
|
+
gimps = Project.new
|
98
|
+
Repos.repos = { Project => { gimps.uuid => gimps } }
|
99
|
+
Repos.project(gimps.uuid).must_equal gimps
|
100
|
+
end
|
89
101
|
end
|
90
|
-
end
|
91
102
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
103
|
+
describe '.projects' do
|
104
|
+
it 'returns all projects' do
|
105
|
+
Repos.repos = { Project => fake(:repo, all: all_projects = fake) }
|
106
|
+
Repos.projects.must_equal all_projects
|
107
|
+
end
|
96
108
|
end
|
97
|
-
end
|
98
109
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
110
|
+
describe '.tasks_for' do
|
111
|
+
it 'returns all tasks for the given project' do
|
112
|
+
project = Project.new
|
113
|
+
tasks = [Task.new, Task.new]
|
114
|
+
task_repo = fake(:repo)
|
115
|
+
stub(task_repo).related_to(project) { tasks }
|
116
|
+
Repos.repos = { Task => task_repo }
|
117
|
+
Repos.tasks_for(project).must_equal tasks
|
118
|
+
end
|
107
119
|
end
|
108
|
-
end
|
109
120
|
|
110
|
-
|
111
|
-
|
121
|
+
describe 'when working on actual database' do
|
122
|
+
before { Repos.db = Sequel.sqlite }
|
112
123
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
it 'makes sure objects can be stored and retrieved' do
|
125
|
+
addr = Addr['127.0.0.1', 1981, :TCP]
|
126
|
+
client = Client.new(addr: addr)
|
127
|
+
project = Project.new(name: 'project name', uuid: UUID.new)
|
128
|
+
task = Task.new(data: 'data', project: project, uuid: UUID.new)
|
129
|
+
reg = Registration.new(addr: addr, client: client, project: project)
|
130
|
+
res = Result.new(addr: addr, client: client, data: 'da', task: task)
|
131
|
+
Repos << client << project << task << reg << res
|
132
|
+
Repos[Client][client.uuid].must_equal client
|
133
|
+
Repos[Project][project.uuid].must_equal project
|
134
|
+
Repos[Registration][reg.uuid].must_equal reg
|
135
|
+
Repos[Result][res.uuid].must_equal res
|
136
|
+
Repos[Task][task.uuid].must_equal task
|
137
|
+
end
|
127
138
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
139
|
+
it 'makes sure objects can be updated' do
|
140
|
+
client = Client.new(addr: Addr['127.0.0.1', 1979, :TCP])
|
141
|
+
Repos << client
|
142
|
+
client.busy = true
|
143
|
+
Repos << client
|
144
|
+
assert Repos[Client][client.uuid].busy
|
145
|
+
end
|
134
146
|
end
|
135
147
|
end
|
136
|
-
end
|
148
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require_relative '../../lib/kamerling/result'
|
3
|
+
|
4
|
+
module Kamerling
|
5
|
+
describe Result do
|
6
|
+
describe '#received_at' do
|
7
|
+
it 'defaults to the current time' do
|
8
|
+
assert Result.new.received_at.between?(Time.now - 1, Time.now + 1)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'defaults to the time of Result’s creation' do
|
12
|
+
Result.new.received_at.wont_equal Result.new.received_at
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,22 +1,27 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
1
3
|
require_relative '../../spec_helper'
|
4
|
+
require_relative '../../../lib/kamerling/server/http'
|
2
5
|
|
3
|
-
module Kamerling
|
4
|
-
|
6
|
+
module Kamerling
|
7
|
+
describe Server::HTTP do
|
8
|
+
let(:addr) { Addr['localhost', 2009, :TCP] }
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
describe '#addr' do
|
11
|
+
it 'returns the server’s host + port as a TCP addr' do
|
12
|
+
Server::HTTP.new(addr: addr).addr.must_equal addr
|
13
|
+
end
|
9
14
|
end
|
10
|
-
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
describe '#start, #stop' do
|
17
|
+
it 'starts/stops a HTTP server on the given host and port' do
|
18
|
+
capture_io do
|
19
|
+
server = Server::HTTP.new(addr: addr).start
|
20
|
+
uri = URI.parse('http://localhost:2009')
|
21
|
+
Net::HTTP.get_response(uri).must_be_kind_of Net::HTTPSuccess
|
22
|
+
server.stop
|
23
|
+
end
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
22
|
-
end
|
27
|
+
end
|