kamerling 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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