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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -13
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +64 -64
  5. data/README.md +18 -1
  6. data/Rakefile +5 -3
  7. data/bin/kamerling +1 -1
  8. data/config/reek.yml +20 -3
  9. data/kamerling.gemspec +16 -13
  10. data/lib/kamerling.rb +2 -28
  11. data/lib/kamerling/addr.rb +17 -3
  12. data/lib/kamerling/client.rb +10 -11
  13. data/lib/kamerling/core_extensions/main.rb +14 -14
  14. data/lib/kamerling/dispatch.rb +13 -0
  15. data/lib/kamerling/handler.rb +16 -25
  16. data/lib/kamerling/http_api.rb +50 -34
  17. data/lib/kamerling/logging.rb +36 -16
  18. data/lib/kamerling/mapper.rb +33 -0
  19. data/lib/kamerling/message.rb +50 -37
  20. data/lib/kamerling/migrations/2_results_received_at.rb +7 -0
  21. data/lib/kamerling/migrations/3_dispatches.rb +17 -0
  22. data/lib/kamerling/migrations/4_registrations_registered_at.rb +7 -0
  23. data/lib/kamerling/migrations/5_clients_type.rb +7 -0
  24. data/lib/kamerling/net_dispatcher.rb +12 -7
  25. data/lib/kamerling/project.rb +7 -3
  26. data/lib/kamerling/receiver.rb +38 -10
  27. data/lib/kamerling/registrar.rb +45 -8
  28. data/lib/kamerling/registration.rb +9 -10
  29. data/lib/kamerling/repo.rb +33 -26
  30. data/lib/kamerling/repos.rb +52 -45
  31. data/lib/kamerling/result.rb +10 -11
  32. data/lib/kamerling/server/http.rb +28 -21
  33. data/lib/kamerling/server/sock.rb +32 -24
  34. data/lib/kamerling/server/tcp.rb +23 -15
  35. data/lib/kamerling/server/udp.rb +24 -16
  36. data/lib/kamerling/server_runner.rb +30 -41
  37. data/lib/kamerling/settings.rb +28 -0
  38. data/lib/kamerling/task.rb +7 -7
  39. data/lib/kamerling/task_dispatcher.rb +31 -22
  40. data/lib/kamerling/uuid.rb +13 -11
  41. data/lib/kamerling/uuid_entity.rb +23 -9
  42. data/lib/kamerling/value.rb +13 -0
  43. data/lib/kamerling/views/clients.slim +3 -1
  44. data/lib/kamerling/views/project.slim +8 -4
  45. data/lib/kamerling/views/projects.slim +7 -1
  46. data/spec/kamerling/addr_spec.rb +32 -22
  47. data/spec/kamerling/client_spec.rb +9 -5
  48. data/spec/kamerling/core_extensions/main_spec.rb +18 -13
  49. data/spec/kamerling/dispatch_spec.rb +16 -0
  50. data/spec/kamerling/handler_spec.rb +24 -34
  51. data/spec/kamerling/http_api_spec.rb +94 -73
  52. data/spec/kamerling/logging_spec.rb +93 -62
  53. data/spec/kamerling/mapper_spec.rb +151 -0
  54. data/spec/kamerling/message_spec.rb +73 -49
  55. data/spec/kamerling/net_dispatcher_spec.rb +22 -16
  56. data/spec/kamerling/receiver_spec.rb +29 -19
  57. data/spec/kamerling/registrar_spec.rb +43 -15
  58. data/spec/kamerling/registration_spec.rb +17 -0
  59. data/spec/kamerling/repo_spec.rb +63 -47
  60. data/spec/kamerling/repos_spec.rb +121 -109
  61. data/spec/kamerling/result_spec.rb +16 -0
  62. data/spec/kamerling/server/http_spec.rb +19 -14
  63. data/spec/kamerling/server/tcp_spec.rb +41 -35
  64. data/spec/kamerling/server/udp_spec.rb +40 -34
  65. data/spec/kamerling/server_runner_spec.rb +62 -53
  66. data/spec/kamerling/settings_spec.rb +36 -0
  67. data/spec/kamerling/task_dispatcher_spec.rb +38 -15
  68. data/spec/kamerling/task_spec.rb +9 -5
  69. data/spec/kamerling/uuid_entity_spec.rb +53 -25
  70. data/spec/kamerling/uuid_spec.rb +19 -16
  71. data/spec/kamerling/value_spec.rb +21 -0
  72. data/spec/spec_helper.rb +3 -6
  73. metadata +54 -8
  74. data/lib/kamerling/core_extensions.rb +0 -1
@@ -1,3 +1,7 @@
1
- module Kamerling class Project < UUIDEntity
2
- attribute :name, String
3
- end end
1
+ require_relative 'uuid_entity'
2
+
3
+ module Kamerling
4
+ class Project < UUIDEntity
5
+ attrs name: String
6
+ end
7
+ end
@@ -1,11 +1,39 @@
1
- module Kamerling class Receiver
2
- def receive addr: req(:addr), client_uuid: req(:client_uuid),
3
- data: req(:data), repos: Repos, task_uuid: req(:task_uuid)
4
- client = repos[Client][client_uuid]
5
- task = repos[Task][task_uuid]
6
- result = Result.new addr: addr, client: client, data: data, task: task
7
- client.busy = false
8
- task.done = true
9
- repos << result << client << task
1
+ require_relative 'client'
2
+ require_relative 'repos'
3
+ require_relative 'result'
4
+ require_relative 'task'
5
+
6
+ module Kamerling
7
+ class Receiver
8
+ def self.receive(addr:, message:, repos: Repos)
9
+ new(addr: addr, message: message, repos: repos).receive
10
+ end
11
+
12
+ def initialize(addr:, message:, repos:)
13
+ @addr, @message, @repos = addr, message, repos
14
+ end
15
+
16
+ def receive
17
+ client.busy = false
18
+ task.done = true
19
+ repos << result << client << task
20
+ end
21
+
22
+ attr_reader :addr, :message, :repos
23
+ private :addr, :message, :repos
24
+
25
+ private
26
+
27
+ def client
28
+ @client ||= repos[Client][message.client_uuid]
29
+ end
30
+
31
+ def result
32
+ Result.new(addr: addr, client: client, data: message.payload, task: task)
33
+ end
34
+
35
+ def task
36
+ @task ||= repos[Task][message.task_uuid]
37
+ end
10
38
  end
11
- end end
39
+ end
@@ -1,9 +1,46 @@
1
- module Kamerling class Registrar
2
- def register addr: req(:addr), client_uuid: req(:client_uuid),
3
- project_uuid: req(:project_uuid), repos: Repos
4
- client = repos[Client][client_uuid]
5
- project = repos[Project][project_uuid]
6
- reg = Registration.new addr: addr, client: client, project: project
7
- repos[Registration] << reg
1
+ require_relative 'client'
2
+ require_relative 'project'
3
+ require_relative 'registration'
4
+ require_relative 'repos'
5
+ require_relative 'uuid'
6
+
7
+ module Kamerling
8
+ class Registrar
9
+ def self.register(addr:, message:, repos: Repos)
10
+ new(addr: addr, message: message, repos: repos).register
11
+ end
12
+
13
+ def initialize(addr:, message:, repos:)
14
+ @addr, @message, @repos = addr, message, repos
15
+ end
16
+
17
+ def register
18
+ client.addr = addr
19
+ repos << client
20
+ repos << registration
21
+ end
22
+
23
+ attr_reader :addr, :message, :repos
24
+ private :addr, :message, :repos
25
+
26
+ private
27
+
28
+ def client
29
+ @client ||= find_or_create_client
30
+ end
31
+
32
+ def find_or_create_client
33
+ repos[Client][message.client_uuid]
34
+ rescue Repo::NotFound
35
+ Client.new(addr: addr, uuid: message.client_uuid)
36
+ end
37
+
38
+ def project
39
+ @project ||= repos[Project][message.project_uuid]
40
+ end
41
+
42
+ def registration
43
+ Registration.new(addr: addr, client: client, project: project)
44
+ end
8
45
  end
9
- end end
46
+ end
@@ -1,12 +1,11 @@
1
- module Kamerling class Registration < UUIDEntity
2
- attribute :addr, Addr
3
- attribute :client, Client
4
- attribute :project, Project
1
+ require_relative 'addr'
2
+ require_relative 'client'
3
+ require_relative 'project'
4
+ require_relative 'uuid_entity'
5
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
6
+ module Kamerling
7
+ class Registration < UUIDEntity
8
+ attrs addr: Addr, client: Client, project: Project, registered_at: Time
9
+ defaults registered_at: -> (*) { Time.now }
11
10
  end
12
- end end
11
+ end
@@ -1,32 +1,39 @@
1
- module Kamerling class Repo
2
- NotFound = Class.new RuntimeError
1
+ require 'sequel'
2
+ require_relative 'mapper'
3
3
 
4
- def initialize klass, source
5
- @klass, @source = klass, source
6
- end
4
+ module Kamerling
5
+ class Repo
6
+ NotFound = Class.new(RuntimeError)
7
7
 
8
- def << object
9
- hash = object.to_h
10
- warn_off { source << hash }
11
- rescue Sequel::UniqueConstraintViolation
12
- warn_off { source.where(uuid: object.uuid).update hash }
13
- end
8
+ def initialize(klass, source, mapper: Mapper)
9
+ @klass = klass
10
+ @mapper = mapper
11
+ @source = source
12
+ end
14
13
 
15
- def [] uuid
16
- hash = warn_off { source[uuid: uuid] }
17
- fail NotFound, "#{klass} with UUID #{uuid}" unless hash
18
- klass.from_h hash
19
- end
14
+ def <<(object)
15
+ hash = mapper.to_h(object)
16
+ warn_off { source << hash }
17
+ rescue Sequel::UniqueConstraintViolation
18
+ warn_off { source.where(uuid: object.uuid).update hash }
19
+ end
20
20
 
21
- def all
22
- source.all.map { |hash| klass.from_h hash }
23
- end
21
+ def [](uuid)
22
+ hash = warn_off { source[uuid: uuid] }
23
+ fail NotFound, "#{klass} with UUID #{uuid}" unless hash
24
+ mapper.from_h(klass, hash)
25
+ end
24
26
 
25
- def related_to object
26
- key = "#{object.class.name.split('::').last.downcase}_uuid".to_sym
27
- source.where(key => object.uuid).map { |hash| klass.from_h hash }
28
- end
27
+ def all
28
+ source.all.map { |hash| mapper.from_h(klass, hash) }
29
+ end
30
+
31
+ def related_to(object)
32
+ key = "#{object.class.name.split('::').last.downcase}_uuid".to_sym
33
+ source.where(key => object.uuid).map { |hash| mapper.from_h(klass, hash) }
34
+ end
29
35
 
30
- attr_reader :klass, :source
31
- private :klass, :source
32
- end end
36
+ attr_reader :klass, :mapper, :source
37
+ private :klass, :mapper, :source
38
+ end
39
+ end
@@ -1,65 +1,72 @@
1
1
  warn_off { require 'sequel' }
2
+ require_relative 'client'
3
+ require_relative 'project'
4
+ require_relative 'registration'
5
+ require_relative 'repo'
6
+ require_relative 'task'
2
7
 
3
8
  Sequel.extension :migration
4
9
 
5
- module Kamerling class Repos
6
- class << self
7
- attr_writer :repos
10
+ module Kamerling
11
+ class Repos
12
+ class << self
13
+ attr_writer :repos
8
14
 
9
- def << object
10
- repos[object.class] << object
11
- self
12
- end
15
+ def <<(object)
16
+ repos[object.class] << object
17
+ self
18
+ end
13
19
 
14
- def [] klass
15
- repos[klass]
16
- end
20
+ def [](klass)
21
+ repos[klass]
22
+ end
17
23
 
18
- def clients
19
- repos[Client].all
20
- end
24
+ def clients
25
+ repos[Client].all
26
+ end
21
27
 
22
- def clients_for project
23
- repos[Registration].related_to(project).map(&:client)
24
- end
28
+ def clients_for(project)
29
+ repos[Registration].related_to(project).map(&:client)
30
+ end
25
31
 
26
- def db= db
27
- warn_off { Sequel::Migrator.run db, "#{__dir__}/migrations" }
28
- @repos = nil
29
- @db = db
30
- end
32
+ def db=(db)
33
+ warn_off { Sequel::Migrator.run db, "#{__dir__}/migrations" }
34
+ @repos = nil
35
+ @db = db
36
+ end
31
37
 
32
- def free_clients_for project
33
- clients_for(project).reject(&:busy)
34
- end
38
+ def free_clients_for(project)
39
+ clients_for(project).reject(&:busy)
40
+ end
35
41
 
36
- def next_task_for project
37
- repos[Task].related_to(project).reject(&:done).first
38
- end
42
+ def next_task_for(project)
43
+ repos[Task].related_to(project).reject(&:done).first
44
+ end
39
45
 
40
- def project project_uuid
41
- repos[Project][project_uuid]
42
- end
46
+ def project(project_uuid)
47
+ repos[Project][project_uuid]
48
+ end
43
49
 
44
- def projects
45
- repos[Project].all
46
- end
50
+ def projects
51
+ repos[Project].all
52
+ end
47
53
 
48
- def tasks_for project
49
- repos[Task].related_to project
50
- end
54
+ def tasks_for(project)
55
+ repos[Task].related_to(project)
56
+ end
51
57
 
52
- private
58
+ private
53
59
 
54
- def db
55
- @db ||= self.db = Sequel.sqlite
56
- end
60
+ def db
61
+ @db ||= self.db = Sequel.sqlite
62
+ end
57
63
 
58
- def repos
59
- @repos ||= Hash.new do |repos, klass|
60
- table = "#{klass.name.split('::').last.downcase}s".to_sym
61
- repos[klass] = Repo.new klass, warn_off { db[table] }
64
+ def repos
65
+ @repos ||= Hash.new do |repos, klass|
66
+ table = "#{klass.name.split('::').last.downcase}s".to_sym
67
+ repos[klass] = Repo.new(klass, warn_off { db[table] })
68
+ end
62
69
  end
63
70
  end
64
71
  end
65
- end end
72
+ end
@@ -1,13 +1,12 @@
1
- module Kamerling class Result < UUIDEntity
2
- attribute :addr, Addr
3
- attribute :client, Client
4
- attribute :data, String
5
- attribute :task, Task
1
+ require_relative 'addr'
2
+ require_relative 'client'
3
+ require_relative 'task'
4
+ require_relative 'uuid_entity'
6
5
 
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
6
+ module Kamerling
7
+ class Result < UUIDEntity
8
+ attrs addr: Addr, client: Client, data: String, received_at: Time,
9
+ task: Task
10
+ defaults received_at: -> (*) { Time.now }
12
11
  end
13
- end end
12
+ end
@@ -1,26 +1,33 @@
1
- module Kamerling module Server class HTTP
2
- attr_reader :addr
1
+ require 'rack'
2
+ require_relative '../http_api'
3
3
 
4
- def initialize addr: req(:addr)
5
- @addr = addr
6
- end
4
+ module Kamerling
5
+ module Server
6
+ class HTTP
7
+ attr_reader :addr
7
8
 
8
- def join
9
- thread.join
10
- end
9
+ def initialize(addr:)
10
+ @addr = addr
11
+ end
11
12
 
12
- def start
13
- @thread = Thread.new do
14
- Rack::Handler::WEBrick.run HTTPAPI, Host: addr.host, Port: addr.port
15
- end
16
- loop { break if addr.connectable? }
17
- self
18
- end
13
+ def join
14
+ thread.join
15
+ end
19
16
 
20
- def stop
21
- thread.exit.join
22
- end
17
+ def start
18
+ @thread = Thread.new do
19
+ Rack::Handler::WEBrick.run HTTPAPI, Host: addr.host, Port: addr.port
20
+ end
21
+ loop { break if addr.connectable? }
22
+ self
23
+ end
24
+
25
+ def stop
26
+ thread.exit.join
27
+ end
23
28
 
24
- attr_reader :thread
25
- private :thread
26
- end end end
29
+ attr_reader :thread
30
+ private :thread
31
+ end
32
+ end
33
+ end
@@ -1,32 +1,40 @@
1
- module Kamerling module Server class Sock
2
- attr_reader :addr
1
+ require_relative '../handler'
2
+ require_relative '../message'
3
3
 
4
- def initialize addr: req(:addr), handler: Handler.new
5
- @addr = addr
6
- @handler = handler
7
- end
4
+ module Kamerling
5
+ module Server
6
+ class Sock
7
+ attr_reader :addr
8
8
 
9
- def join
10
- thread.join
11
- end
9
+ def initialize(addr:, handler: Handler.new)
10
+ @addr = addr
11
+ @handler = handler
12
+ end
12
13
 
13
- def start
14
- @thread = Thread.new { run_loop }
15
- wait_till_started
16
- self
17
- end
14
+ def join
15
+ thread.join
16
+ end
18
17
 
19
- def stop
20
- thread.exit.join
21
- end
18
+ def start
19
+ @thread = Thread.new { run_loop }
20
+ wait_till_started
21
+ self
22
+ end
23
+
24
+ def stop
25
+ thread.exit.join
26
+ end
22
27
 
23
- attr_reader :handler, :thread
24
- private :handler, :thread
28
+ attr_reader :handler, :thread
29
+ private :handler, :thread
25
30
 
26
- private
31
+ private
27
32
 
28
- def handle input, client_addr
29
- handler.handle input, client_addr
30
- rescue Handler::UnknownInput
33
+ def handle(input, client_addr)
34
+ handler.handle Message.parse(input), client_addr
35
+ rescue Message::UnknownType
36
+ nil
37
+ end
38
+ end
31
39
  end
32
- end end end
40
+ end