cuboid 0.0.2alpha → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +1 -0
- data/cuboid.gemspec +2 -2
- data/lib/cuboid/option_groups/dispatcher.rb +16 -0
- data/lib/cuboid/option_groups/paths.rb +12 -3
- data/lib/cuboid/processes/dispatchers.rb +15 -1
- data/lib/cuboid/processes/instances.rb +13 -1
- data/lib/cuboid/processes/schedulers.rb +15 -2
- data/lib/cuboid/rpc/server/application_wrapper.rb +4 -3
- data/lib/cuboid/rpc/server/dispatcher.rb +36 -7
- data/lib/cuboid/rpc/server/scheduler.rb +2 -1
- data/lib/version +1 -1
- data/spec/cuboid/option_groups/paths_spec.rb +6 -3
- data/spec/cuboid/rpc/server/dispatcher_spec.rb +147 -32
- data/spec/support/logs/Dispatcher - 1520492-37227.log +6 -0
- data/spec/support/logs/Dispatcher - 1520680-13689.log +6 -0
- data/spec/support/logs/Dispatcher - 1520682-24167.log +6 -0
- data/spec/support/logs/Dispatcher - 1520688-42731.log +6 -0
- data/spec/support/logs/Dispatcher - 1520690-5750.log +10 -0
- data/spec/support/logs/Dispatcher - 1520692-55183.log +10 -0
- data/spec/support/logs/Dispatcher - 1520695-39752.log +10 -0
- data/spec/support/logs/Dispatcher - 1520697-44327.log +10 -0
- data/spec/support/logs/Dispatcher - 1520699-58785.log +10 -0
- data/spec/support/logs/Dispatcher - 1520701-60952.log +10 -0
- data/spec/support/logs/Dispatcher - 1520796-50420.log +6 -0
- data/spec/support/logs/Dispatcher - 1520894-56883.log +6 -0
- data/spec/support/logs/Dispatcher - 1520896-21419.log +6 -0
- data/spec/support/logs/Dispatcher - 1520898-62584.log +6 -0
- data/spec/support/logs/Dispatcher - 1520900-59721.log +6 -0
- data/spec/support/logs/Dispatcher - 1520910-51632.log +6 -0
- data/spec/support/logs/Dispatcher - 1520920-21801.log +6 -0
- data/spec/support/logs/Dispatcher - 1520930-49223.log +6 -0
- data/spec/support/logs/Dispatcher - 1520933-34241.log +6 -0
- data/spec/support/logs/Dispatcher - 1520935-64571.log +6 -0
- data/spec/support/logs/Dispatcher - 1520937-50734.log +6 -0
- data/spec/support/logs/Dispatcher - 1520939-60841.log +6 -0
- data/spec/support/logs/Dispatcher - 1520944-8124.log +6 -0
- data/spec/support/logs/Dispatcher - 1520946-25192.log +16 -0
- data/spec/support/logs/Dispatcher - 1520948-9752.log +14 -0
- data/spec/support/logs/Dispatcher - 1520952-45543.log +10 -0
- data/spec/support/logs/Dispatcher - 1520958-36653.log +16 -0
- data/spec/support/logs/Dispatcher - 1520960-17456.log +14 -0
- data/spec/support/logs/Dispatcher - 1520964-5774.log +10 -0
- data/spec/support/logs/Dispatcher - 1520976-40848.log +16 -0
- data/spec/support/logs/Dispatcher - 1520978-29867.log +14 -0
- data/spec/support/logs/Dispatcher - 1520982-17715.log +10 -0
- data/spec/support/logs/Dispatcher - 1520987-8925.log +16 -0
- data/spec/support/logs/Dispatcher - 1520989-25480.log +14 -0
- data/spec/support/logs/Dispatcher - 1520993-5124.log +10 -0
- data/spec/support/logs/Dispatcher - 1520999-12901.log +16 -0
- data/spec/support/logs/Dispatcher - 1521004-32265.log +14 -0
- data/spec/support/logs/Dispatcher - 1521008-33455.log +10 -0
- data/spec/support/logs/Dispatcher - 1521014-13779.log +6 -0
- data/spec/support/logs/Dispatcher - 1521017-14755.log +6 -0
- data/spec/support/logs/Dispatcher - 1521022-48687.log +6 -0
- data/spec/support/logs/Dispatcher - 1521024-59097.log +6 -0
- data/spec/support/logs/Dispatcher - 1521034-12604.log +6 -0
- data/spec/support/logs/Dispatcher - 1521038-64272.log +6 -0
- data/spec/support/logs/Dispatcher - 1521043-8680.log +6 -0
- data/spec/support/logs/Dispatcher - 1521047-22949.log +6 -0
- data/spec/support/logs/Dispatcher - 1521051-3355.log +6 -0
- data/spec/support/logs/Dispatcher - 1521074-12332.log +6 -0
- data/spec/support/logs/Dispatcher - 1521118-53130.log +16 -0
- data/spec/support/logs/Dispatcher - 1521128-47137.log +14 -0
- data/spec/support/logs/Dispatcher - 1521136-30328.log +10 -0
- data/spec/support/logs/Dispatcher - 1521161-21329.log +16 -0
- data/spec/support/logs/Dispatcher - 1521172-19183.log +14 -0
- data/spec/support/logs/Dispatcher - 1521179-34902.log +10 -0
- data/spec/support/logs/Dispatcher - 1521190-20155.log +16 -0
- data/spec/support/logs/Dispatcher - 1521204-43843.log +14 -0
- data/spec/support/logs/Dispatcher - 1521211-23972.log +10 -0
- data/spec/support/logs/Dispatcher - 1521237-20879.log +10 -0
- data/spec/support/logs/Dispatcher - 1521239-61999.log +10 -0
- data/spec/support/logs/Dispatcher - 1521242-20975.log +16 -0
- data/spec/support/logs/Dispatcher - 1521246-28409.log +14 -0
- data/spec/support/logs/Dispatcher - 1521250-58505.log +10 -0
- data/spec/support/logs/Dispatcher - 1521262-53292.log +6 -0
- data/spec/support/logs/Dispatcher - 1521266-42758.log +6 -0
- data/spec/support/logs/Dispatcher - 1521277-4215.log +6 -0
- data/spec/support/logs/Dispatcher - 1521292-16086.log +6 -0
- data/spec/support/logs/Dispatcher - 1521301-42112.log +6 -0
- data/spec/support/logs/Dispatcher - 1521312-61196.log +6 -0
- data/spec/support/logs/Dispatcher - 1521316-23353.log +6 -0
- data/spec/support/logs/Dispatcher - 1521321-46361.log +6 -0
- data/spec/support/logs/Dispatcher - 1521438-46016.log +6 -0
- data/spec/support/logs/Dispatcher - 1521454-49862.log +6 -0
- data/spec/support/logs/Dispatcher - 1521470-54737.log +6 -0
- data/spec/support/logs/Instance - 1521353-26273.error.log +105 -0
- data/spec/support/logs/Instance - 1521355-56591.error.log +105 -0
- data/spec/support/logs/Instance - 1521363-26218.error.log +105 -0
- data/spec/support/logs/Scheduler - 1520469-35703.log +3 -0
- data/spec/support/logs/Scheduler - 1520473-60524.log +6 -0
- data/spec/support/logs/Scheduler - 1520509-34951.log +3 -0
- data/spec/support/logs/Scheduler - 1520517-31455.log +6 -0
- data/spec/support/logs/Scheduler - 1520529-43808.log +4 -0
- data/spec/support/logs/Scheduler - 1520536-23387.log +1 -0
- data/spec/support/logs/Scheduler - 1520549-48260.log +3 -0
- data/spec/support/logs/Scheduler - 1520563-45636.log +6 -0
- data/spec/support/logs/Scheduler - 1520599-40643.log +3 -0
- data/spec/support/logs/Scheduler - 1520608-54106.log +6 -0
- data/spec/support/logs/Scheduler - 1520629-24722.log +3 -0
- data/spec/support/logs/Scheduler - 1520637-61755.log +6 -0
- data/spec/support/logs/Scheduler - 1520663-17447.log +4 -0
- data/spec/support/logs/Scheduler - 1520671-38282.log +6 -0
- data/spec/support/logs/Scheduler - 1520703-33082.log +1 -0
- data/spec/support/logs/Scheduler - 1520706-22309.log +1 -0
- data/spec/support/logs/Scheduler - 1520709-1816.log +1 -0
- data/spec/support/logs/Scheduler - 1520711-19998.log +1 -0
- data/spec/support/logs/Scheduler - 1520714-47570.log +1 -0
- data/spec/support/logs/Scheduler - 1520723-18521.log +1 -0
- data/spec/support/logs/Scheduler - 1520725-40913.log +3 -0
- data/spec/support/logs/Scheduler - 1520749-45742.log +6 -0
- data/spec/support/logs/Scheduler - 1520759-44350.log +4 -0
- data/spec/support/logs/Scheduler - 1520770-53219.log +1 -0
- data/spec/support/logs/Scheduler - 1520773-54792.log +1 -0
- data/spec/support/logs/Scheduler - 1520777-19636.log +1 -0
- data/spec/support/logs/Scheduler - 1520780-51801.log +1 -0
- data/spec/support/logs/Scheduler - 1520782-9652.log +3 -0
- data/spec/support/logs/Scheduler - 1520786-59472.log +1 -0
- data/spec/support/logs/Scheduler - 1520789-1603.log +1 -0
- data/spec/support/logs/Scheduler - 1520792-35476.log +1 -0
- data/spec/support/logs/Scheduler - 1521410-47324.log +16 -0
- data/spec/support/logs/Scheduler - 1521422-33737.log +6 -0
- data/spec/support/logs/Scheduler - 1521433-36637.log +6 -0
- data/spec/support/logs/Scheduler - 1521440-15066.log +6 -0
- data/spec/support/logs/Scheduler - 1521456-48637.log +3 -0
- data/spec/support/logs/Scheduler - 1521472-54425.log +5 -0
- data/spec/support/logs/Scheduler - 1521496-12923.log +1 -0
- data/spec/support/logs/Scheduler - 1521518-46819.log +1 -0
- data/spec/support/logs/Scheduler - 1521522-21417.log +1 -0
- data/spec/support/logs/Scheduler - 1521525-35088.log +1 -0
- data/spec/support/logs/Scheduler - 1521528-13676.log +1 -0
- data/spec/support/logs/Scheduler - 1521530-48176.log +1 -0
- data/spec/support/logs/Scheduler - 1521532-13207.log +1 -0
- data/spec/support/logs/Scheduler - 1521535-5799.log +3 -0
- data/spec/support/logs/Scheduler - 1521543-62784.log +3 -0
- data/spec/support/logs/Scheduler - 1521551-10263.log +3 -0
- data/spec/support/logs/Scheduler - 1521556-56026.log +3 -0
- data/spec/support/logs/Scheduler - 1521560-14551.log +4 -0
- data/spec/support/logs/Scheduler - 1521573-47584.log +1 -0
- data/spec/support/logs/Scheduler - 1521578-14443.log +4 -0
- data/spec/support/logs/Scheduler - 1521580-60337.log +1 -0
- data/spec/support/logs/Scheduler - 1521583-52039.log +1 -0
- data/spec/support/logs/Scheduler - 1521586-1500.log +16 -0
- data/spec/support/logs/Scheduler - 1521598-61298.log +4 -0
- data/spec/support/logs/Scheduler - 1521602-61490.log +1 -0
- data/spec/support/logs/Scheduler - 1521604-29209.log +1 -0
- data/spec/support/logs/Scheduler - 1521606-47734.log +1 -0
- data/spec/support/logs/Scheduler - 1521612-63269.log +1 -0
- data/spec/support/logs/Scheduler - 1521614-47018.log +3 -0
- data/spec/support/logs/Scheduler - 1521619-32411.log +1 -0
- data/spec/support/logs/Scheduler - 1521621-42861.log +1 -0
- data/spec/support/logs/Scheduler - 1521623-56258.log +1 -0
- data/spec/support/logs/Scheduler - 1521627-9487.log +1 -0
- data/spec/support/logs/Scheduler - 1521630-3345.log +1 -0
- data/spec/support/logs/Scheduler - 1521632-47325.log +1 -0
- data/spec/support/logs/Scheduler - 1521635-22156.log +2 -0
- data/spec/support/logs/error-1520329.log +797 -0
- data/spec/support/logs/output_spec_1520329.log +390 -0
- data/spec/support/reports/003bed585153336c2548d1c60a026a3e.crf +0 -0
- data/spec/support/reports/30e3c7a8c13e9b40a0a443a5e5a4ff94.crf +0 -0
- data/spec/support/reports/31655751a9f0eee91e588bc796985b1e.crf +0 -0
- data/spec/support/reports/40801b7993c0ed919b73242a9c078dde.crf +0 -0
- data/spec/support/reports/4719b89667e92bb80102f4b0bb4c0c75.crf +0 -0
- data/spec/support/reports/4e765a3d2870d2763ea72167bd3db9d6.crf +0 -0
- data/spec/support/reports/61968f732d8ae715c104175e43679915.crf +0 -0
- data/spec/support/reports/63446a8ec637d9991b8c6a1151ae59a9.crf +0 -0
- data/spec/support/reports/737144b18305c7a115ad7964b9bbe41c.crf +0 -0
- data/spec/support/reports/73fe5f7adf905045c3fe4669bdf60d02.crf +0 -0
- data/spec/support/reports/86cd396db9ef97472876f32e57c44ce7.crf +0 -0
- data/spec/support/reports/8a031ac2b2730dfd07a1d1ca870299f2.crf +0 -0
- data/spec/support/reports/8e16ac74484ee5d8cf7073fe22adf787.crf +0 -0
- data/spec/support/reports/8eff857213ab6ff712a0b0e8582855c9.crf +0 -0
- data/spec/support/reports/9e0e6ed8718973b3d4e63bbb7dd1d1c6.crf +0 -0
- data/spec/support/reports/a9c88f967d09cb9c4e8e1180cfb24828.crf +0 -0
- data/spec/support/reports/ba32970a64686e45ec8caa5032f65c2e.crf +0 -0
- data/spec/support/reports/cceb7596659fd619ab4438953cbda78b.crf +0 -0
- data/spec/support/reports/d2e0f4558b605ffd1215e9226815b951.crf +0 -0
- data/spec/support/snapshots/Cuboid 2022-01-24 14_38_16 +0200 8238609e31cedaf1bcb89205f9d42121.csf +0 -0
- data/spec/support/snapshots/Cuboid 2022-01-24 14_38_30 +0200 68690b002e79c7bc9e3aabfcbc7ac5a7.csf +0 -0
- data/spec/support/snapshots/Cuboid 2022-01-24 14_46_39 +0200 6fd3c9491d3e784e18f9c3c0d9deddec.csf +0 -0
- data/spec/support/snapshots/Cuboid 2022-01-24 14_46_44 +0200 c3a012fba59210bc7c169afb0565d5a8.csf +0 -0
- data/spec/support/snapshots/Cuboid 2022-01-24 14_46_46 +0200 e4c1ce35d8e62e6a16f84eccd36b2283.csf +0 -0
- metadata +350 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b01651b87b7bf659764002cbb1aaa3b8293caf047f9675874b7393dd36c54ced
|
4
|
+
data.tar.gz: 0b831b738a29e23eecdb949e17079294eb75b57cc902395ec54021cd2d923bee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4aaca66ce49f16888f68e39d84c4d2d9e3f81b7cc8551b31ee6f74505d0c379a6aa92443e698724da65babd8d32c3f9cc5695c272cca4d5d0c2e4d9637d50f6a
|
7
|
+
data.tar.gz: 258a9295ef9d4765ef9f8cc9ff60ec53e2ee2b11cb342069db7574853ce7db8c1bceb242c80012170a52bba8b9e8f1a489d7969b150e0be15135aa70a0ba15b6
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -14,6 +14,7 @@ It offers:
|
|
14
14
|
* No need to setup a topology manually, _**Dispatchers**_ will reach
|
15
15
|
convergence on their own, just point them to an existing _**Grid**_ member.
|
16
16
|
* Scaling up and down can be easily achieved by _plugging_ or _unplugging_ nodes.
|
17
|
+
* Horizontal (`default`) and vertical workload distribution strategies available.
|
17
18
|
* Fault tolerant -- one application per process (_**Instance**_).
|
18
19
|
* Self-healing -- keeps an eye out for disappearing and also re-appearing members.
|
19
20
|
* A clean and simple framework for application development.
|
data/cuboid.gemspec
CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.add_dependency 'concurrent-ruby-ext', '1.1.8'
|
36
36
|
|
37
37
|
# For compressing/decompressing system state archives.
|
38
|
-
s.add_dependency 'rubyzip', '
|
38
|
+
s.add_dependency 'rubyzip', '2.3.0'
|
39
39
|
|
40
40
|
s.add_dependency 'childprocess', '0.8.0'
|
41
41
|
|
@@ -47,7 +47,7 @@ Gem::Specification.new do |s|
|
|
47
47
|
s.add_dependency 'oj_mimic_json', '1.0.1'
|
48
48
|
|
49
49
|
# Web server
|
50
|
-
s.add_dependency 'puma', '
|
50
|
+
s.add_dependency 'puma', '5.5.2'
|
51
51
|
|
52
52
|
s.add_dependency 'rack', '2.2.3'
|
53
53
|
s.add_dependency 'rack-test'
|
@@ -5,6 +5,8 @@ module Cuboid::OptionGroups
|
|
5
5
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
|
6
6
|
class Dispatcher < Cuboid::OptionGroup
|
7
7
|
|
8
|
+
STRATEGIES = Set.new([:horizontal, :vertical])
|
9
|
+
|
8
10
|
# @return [String]
|
9
11
|
# URL of a {RPC::Server::Dispatcher}.
|
10
12
|
attr_accessor :url
|
@@ -29,10 +31,24 @@ class Dispatcher < Cuboid::OptionGroup
|
|
29
31
|
# Dispatcher name.
|
30
32
|
attr_accessor :name
|
31
33
|
|
34
|
+
attr_accessor :strategy
|
35
|
+
|
32
36
|
set_defaults(
|
37
|
+
strategy: :horizontal,
|
33
38
|
ping_interval: 5.0,
|
34
39
|
instance_port_range: [1025, 65535]
|
35
40
|
)
|
36
41
|
|
42
|
+
def strategy=( type )
|
43
|
+
return @strategy = defaults[:strategy] if !type
|
44
|
+
|
45
|
+
type = type.to_sym
|
46
|
+
if !STRATEGIES.include? type
|
47
|
+
fail ArgumentError, "Unknown strategy type: #{type}"
|
48
|
+
end
|
49
|
+
|
50
|
+
@strategy = type
|
51
|
+
end
|
52
|
+
|
37
53
|
end
|
38
54
|
end
|
@@ -74,16 +74,21 @@ class Paths < Cuboid::OptionGroup
|
|
74
74
|
|
75
75
|
def initialize
|
76
76
|
@root = self.root_path
|
77
|
+
FileUtils.mkdir_p home_path
|
77
78
|
|
78
|
-
@snapshots = self.config['snapshots'] ||
|
79
|
-
|
79
|
+
@snapshots = self.config['snapshots'] || home_path + 'snapshots/'
|
80
|
+
FileUtils.mkdir_p @snapshots
|
81
|
+
|
82
|
+
@reports = self.config['reports'] || home_path + 'reports/'
|
83
|
+
FileUtils.mkdir_p @reports
|
80
84
|
|
81
85
|
if ENV['CUBOID_LOGDIR'].to_s != ''
|
82
86
|
@logs = "#{ENV['CUBOID_LOGDIR']}/"
|
83
87
|
elsif self.config['logs']
|
84
88
|
@logs = self.config['logs']
|
85
89
|
else
|
86
|
-
@logs = "#{
|
90
|
+
@logs = "#{home_path}logs/"
|
91
|
+
FileUtils.mkdir_p @logs
|
87
92
|
end
|
88
93
|
|
89
94
|
@lib = @root + 'lib/cuboid/'
|
@@ -98,6 +103,10 @@ class Paths < Cuboid::OptionGroup
|
|
98
103
|
tmpdir
|
99
104
|
end
|
100
105
|
|
106
|
+
def home_path
|
107
|
+
@home_path ||= "#{ENV['HOME']}/.cuboid/"
|
108
|
+
end
|
109
|
+
|
101
110
|
def root_path
|
102
111
|
self.class.root_path
|
103
112
|
end
|
@@ -54,16 +54,30 @@ class Dispatchers
|
|
54
54
|
#
|
55
55
|
# @return [RPC::Client::Dispatcher]
|
56
56
|
def spawn( options = {} )
|
57
|
+
options = options.dup
|
57
58
|
fork = options.delete(:fork)
|
58
59
|
|
60
|
+
options[:ssl] ||= {
|
61
|
+
server: {},
|
62
|
+
client: {}
|
63
|
+
}
|
64
|
+
|
59
65
|
options = {
|
60
66
|
dispatcher: {
|
67
|
+
name: options[:name],
|
61
68
|
neighbour: options[:neighbour],
|
69
|
+
strategy: options[:strategy],
|
62
70
|
},
|
63
71
|
rpc: {
|
64
72
|
server_port: options[:port] || Utilities.available_port,
|
65
73
|
server_address: options[:address] || '127.0.0.1',
|
66
|
-
server_external_address: options[:external_address]
|
74
|
+
server_external_address: options[:external_address],
|
75
|
+
|
76
|
+
ssl_ca: options[:ssl][:ca],
|
77
|
+
server_ssl_private_key: options[:ssl][:server][:private_key],
|
78
|
+
server_ssl_certificate: options[:ssl][:server][:certificate],
|
79
|
+
client_ssl_private_key: options[:ssl][:client][:private_key],
|
80
|
+
client_ssl_certificate: options[:ssl][:client][:certificate],
|
67
81
|
},
|
68
82
|
paths: {
|
69
83
|
application: options[:application] || Options.paths.application
|
@@ -61,16 +61,28 @@ class Instances
|
|
61
61
|
# @return [RPC::Client::Instance, Integer]
|
62
62
|
# RPC client and PID.
|
63
63
|
def spawn( options = {}, &block )
|
64
|
+
options = options.dup
|
64
65
|
token = options.delete(:token) || Utilities.generate_token
|
65
66
|
fork = options.delete(:fork)
|
66
67
|
|
67
68
|
port_range = options.delete( :port_range )
|
68
69
|
|
70
|
+
options[:ssl] ||= {
|
71
|
+
server: {},
|
72
|
+
client: {}
|
73
|
+
}
|
74
|
+
|
69
75
|
options = {
|
70
76
|
rpc: {
|
71
77
|
server_socket: options[:socket],
|
72
78
|
server_port: options[:port] || Utilities.available_port( port_range ),
|
73
|
-
server_address: options[:address] || '127.0.0.1'
|
79
|
+
server_address: options[:address] || '127.0.0.1',
|
80
|
+
|
81
|
+
ssl_ca: options[:ssl][:ca],
|
82
|
+
server_ssl_private_key: options[:ssl][:server][:private_key],
|
83
|
+
server_ssl_certificate: options[:ssl][:server][:certificate],
|
84
|
+
client_ssl_private_key: options[:ssl][:client][:private_key],
|
85
|
+
client_ssl_certificate: options[:ssl][:client][:certificate],
|
74
86
|
},
|
75
87
|
paths: {
|
76
88
|
application: options[:application] || Options.paths.application
|
@@ -52,16 +52,29 @@ class Schedulers
|
|
52
52
|
#
|
53
53
|
# @return [RPC::Client::Queue]
|
54
54
|
def spawn( options = {} )
|
55
|
+
options = options.dup
|
55
56
|
fork = options.delete(:fork)
|
56
57
|
|
58
|
+
options[:ssl] ||= {
|
59
|
+
server: {},
|
60
|
+
client: {}
|
61
|
+
}
|
62
|
+
|
57
63
|
options = {
|
58
64
|
dispatcher: {
|
59
|
-
url:
|
65
|
+
url: options[:dispatcher],
|
66
|
+
strategy: options[:strategy]
|
60
67
|
},
|
61
68
|
rpc: {
|
62
69
|
server_port: options[:port] || Utilities.available_port,
|
63
70
|
server_address: options[:address] || '127.0.0.1',
|
64
|
-
server_external_address: options[:external_address]
|
71
|
+
server_external_address: options[:external_address],
|
72
|
+
|
73
|
+
ssl_ca: options[:ssl][:ca],
|
74
|
+
server_ssl_private_key: options[:ssl][:server][:private_key],
|
75
|
+
server_ssl_certificate: options[:ssl][:server][:certificate],
|
76
|
+
client_ssl_private_key: options[:ssl][:client][:private_key],
|
77
|
+
client_ssl_certificate: options[:ssl][:client][:certificate],
|
65
78
|
},
|
66
79
|
paths: {
|
67
80
|
application: options[:application] || Options.paths.application
|
@@ -15,9 +15,10 @@ class ApplicationWrapper
|
|
15
15
|
attr_reader :application
|
16
16
|
|
17
17
|
extend Forwardable
|
18
|
-
def_delegators :@application, :suspended?, :suspend!, :status,
|
19
|
-
:pause!, :running?, :status_messages, :paused?,
|
20
|
-
:snapshot_path, :restore!, :resume!, :generate_report
|
18
|
+
def_delegators :@application, :suspended?, :suspending?, :suspend!, :status,
|
19
|
+
:pause!, :running?, :status_messages, :paused?, :pausing?,
|
20
|
+
:snapshot_path, :restore!, :resume!, :generate_report,
|
21
|
+
:abort!, :aborting?, :aborted?
|
21
22
|
|
22
23
|
# {RPC::Server::Application} error namespace.
|
23
24
|
#
|
@@ -31,6 +31,8 @@ class Dispatcher
|
|
31
31
|
|
32
32
|
SERVICE_NAMESPACE = Service
|
33
33
|
|
34
|
+
PREFERENCE_STRATEGIES = Cuboid::OptionGroups::Dispatcher::STRATEGIES
|
35
|
+
|
34
36
|
def initialize( options = Options.instance )
|
35
37
|
@options = options
|
36
38
|
|
@@ -77,13 +79,24 @@ class Dispatcher
|
|
77
79
|
@server.alive?
|
78
80
|
end
|
79
81
|
|
82
|
+
# @param [Symbol] strategy
|
83
|
+
# `:horizontal` -- Pick the Dispatcher with the least amount of workload.
|
84
|
+
# `:vertical` -- Pick the Dispatcher with the most amount of workload.
|
85
|
+
#
|
80
86
|
# @return [String, nil]
|
81
|
-
# Depending on availability:
|
87
|
+
# Depending on strategy and availability:
|
82
88
|
#
|
83
|
-
# * URL of the
|
84
|
-
#
|
85
|
-
# * `nil` if all nodes are at max utilization.
|
86
|
-
|
89
|
+
# * URL of the preferred Dispatcher. If not a grid member it will return
|
90
|
+
# this Dispatcher's URL.
|
91
|
+
# * `nil` if all nodes are at max utilization or on error.
|
92
|
+
# * `ArgumentError` -- On invalid `strategy`.
|
93
|
+
def preferred( strategy = Cuboid::Options.dispatcher.strategy, &block )
|
94
|
+
strategy = strategy.to_sym
|
95
|
+
if !PREFERENCE_STRATEGIES.include? strategy
|
96
|
+
block.call :error_unknown_strategy
|
97
|
+
raise ArgumentError, "Unknown strategy: #{strategy}"
|
98
|
+
end
|
99
|
+
|
87
100
|
if !@node.grid_member?
|
88
101
|
block.call( self.utilization == 1 ? nil : @url )
|
89
102
|
return
|
@@ -94,6 +107,16 @@ class Dispatcher
|
|
94
107
|
nil : [url, utilization]
|
95
108
|
end
|
96
109
|
|
110
|
+
adjust_score_by_strategy = proc do |score|
|
111
|
+
case strategy
|
112
|
+
when :horizontal
|
113
|
+
score
|
114
|
+
|
115
|
+
when :vertical
|
116
|
+
-score
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
97
120
|
each = proc do |neighbour, iter|
|
98
121
|
connect_to_peer( neighbour ).utilization do |utilization|
|
99
122
|
iter.return pick_utilization.call( neighbour, utilization )
|
@@ -110,7 +133,7 @@ class Dispatcher
|
|
110
133
|
next
|
111
134
|
end
|
112
135
|
|
113
|
-
block.call nodes.sort_by { |_, score| score }[0][0]
|
136
|
+
block.call nodes.sort_by { |_, score| adjust_score_by_strategy.call score }[0][0]
|
114
137
|
end
|
115
138
|
|
116
139
|
Arachni::Reactor.global.create_iterator( @node.neighbours ).map( each, after )
|
@@ -133,17 +156,23 @@ class Dispatcher
|
|
133
156
|
# * `nil`: Max utilization, wait for one of the instances to finish and retry.
|
134
157
|
def dispatch( options = {}, &block )
|
135
158
|
options = options.my_symbolize_keys
|
159
|
+
strategy = options.delete(:strategy)
|
136
160
|
owner = options[:owner]
|
137
161
|
helpers = options[:helpers] || {}
|
138
162
|
load_balance = options[:load_balance].nil? ? true : options[:load_balance]
|
139
163
|
|
140
164
|
if load_balance && @node.grid_member?
|
141
|
-
preferred do |url|
|
165
|
+
preferred *[strategy].compact do |url|
|
142
166
|
if !url
|
143
167
|
block.call
|
144
168
|
next
|
145
169
|
end
|
146
170
|
|
171
|
+
if url == :error_unknown_strategy
|
172
|
+
block.call :error_unknown_strategy
|
173
|
+
next
|
174
|
+
end
|
175
|
+
|
147
176
|
connect_to_peer( url ).dispatch( options.merge(
|
148
177
|
helpers: helpers.merge( via: @url ),
|
149
178
|
load_balance: false
|
data/lib/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
@@ -70,7 +70,7 @@ describe Cuboid::OptionGroups::Paths do
|
|
70
70
|
|
71
71
|
describe '#logs' do
|
72
72
|
it 'returns the default location' do
|
73
|
-
expect(subject.logs).to eq("#{subject.
|
73
|
+
expect(subject.logs).to eq("#{subject.home_path}logs/")
|
74
74
|
end
|
75
75
|
|
76
76
|
context 'when the CUBOID_LOGDIR environment variable' do
|
@@ -91,13 +91,14 @@ describe Cuboid::OptionGroups::Paths do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
expect(described_class.new.logs).to eq('logs-stuff/')
|
94
|
+
@created_resources << described_class.new.logs
|
94
95
|
end
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
98
99
|
describe '#snapshots' do
|
99
100
|
it 'returns the default location' do
|
100
|
-
expect(subject.snapshots).to eq("#{subject.
|
101
|
+
expect(subject.snapshots).to eq("#{subject.home_path}snapshots/")
|
101
102
|
end
|
102
103
|
|
103
104
|
context "when #{described_class}.config['snapshots']" do
|
@@ -109,13 +110,14 @@ describe Cuboid::OptionGroups::Paths do
|
|
109
110
|
end
|
110
111
|
|
111
112
|
expect(described_class.new.snapshots).to eq('snapshots-stuff/')
|
113
|
+
@created_resources << described_class.new.snapshots
|
112
114
|
end
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
116
118
|
describe '#reports' do
|
117
119
|
it 'returns the default location' do
|
118
|
-
expect(subject.reports).to eq("#{subject.
|
120
|
+
expect(subject.reports).to eq("#{subject.home_path}reports/")
|
119
121
|
end
|
120
122
|
|
121
123
|
context "when #{described_class}.config['reports']" do
|
@@ -127,6 +129,7 @@ describe Cuboid::OptionGroups::Paths do
|
|
127
129
|
end
|
128
130
|
|
129
131
|
expect(described_class.new.reports).to eq('reports-stuff/')
|
132
|
+
@created_resources << described_class.new.reports
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
@@ -20,11 +20,44 @@ describe Cuboid::RPC::Server::Dispatcher do
|
|
20
20
|
|
21
21
|
describe '#preferred' do
|
22
22
|
context 'when the dispatcher is a grid member' do
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
context 'and strategy is' do
|
24
|
+
context :horizontal do
|
25
|
+
it 'returns the URL of least burdened Dispatcher' do
|
26
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
27
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
26
28
|
|
27
|
-
|
29
|
+
expect(subject.preferred( :horizontal )).to eq(subject.url)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context :vertical do
|
34
|
+
it 'returns the URL of most burdened Dispatcher' do
|
35
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
36
|
+
d = dispatcher_spawn( neighbour: subject.url )
|
37
|
+
d.dispatch( load_balance: false )
|
38
|
+
d.dispatch( load_balance: false )
|
39
|
+
|
40
|
+
expect(subject.preferred( :vertical )).to eq(d.url)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'default' do
|
45
|
+
it 'returns the URL of least burdened Dispatcher' do
|
46
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
47
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
48
|
+
|
49
|
+
expect(subject.preferred).to eq(subject.url)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'other' do
|
54
|
+
it 'returns :error_unknown_strategy' do
|
55
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
56
|
+
dispatcher_spawn( neighbour: subject.url ).dispatch( load_balance: false )
|
57
|
+
|
58
|
+
expect(subject.preferred( :blah )).to eq('error_unknown_strategy')
|
59
|
+
end
|
60
|
+
end
|
28
61
|
end
|
29
62
|
|
30
63
|
context 'and all Dispatchers are at max utilization' do
|
@@ -154,40 +187,122 @@ describe Cuboid::RPC::Server::Dispatcher do
|
|
154
187
|
context 'when a Grid member' do
|
155
188
|
let(:slots) { 4 }
|
156
189
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
190
|
+
context 'and strategy is' do
|
191
|
+
context :horizontal do
|
192
|
+
it 'provides Instances from the least burdened Dispatcher' do
|
193
|
+
d1 = dispatcher_spawn(
|
194
|
+
address: '127.0.0.1',
|
195
|
+
application: "#{fixtures_path}/mock_app.rb"
|
196
|
+
)
|
162
197
|
|
163
|
-
|
164
|
-
|
198
|
+
3.times do
|
199
|
+
d1.dispatch( load_balance: false )
|
200
|
+
end
|
201
|
+
|
202
|
+
d2 = dispatcher_spawn(
|
203
|
+
address: '127.0.0.2',
|
204
|
+
neighbour: d1.url,
|
205
|
+
application: "#{fixtures_path}/mock_app.rb"
|
206
|
+
)
|
207
|
+
|
208
|
+
2.times do
|
209
|
+
d2.dispatch( load_balance: false )
|
210
|
+
end
|
211
|
+
|
212
|
+
d3 = dispatcher_spawn(
|
213
|
+
address: '127.0.0.3',
|
214
|
+
neighbour: d1.url,
|
215
|
+
application: "#{fixtures_path}/mock_app.rb"
|
216
|
+
)
|
217
|
+
d3.dispatch( load_balance: false )
|
218
|
+
preferred = d3.url.split( ':' ).first
|
219
|
+
|
220
|
+
expect(d3.dispatch(strategy: :horizontal )['url'].split( ':' ).first).to eq(preferred)
|
221
|
+
expect(%W{127.0.0.3 127.0.0.2}).to include d1.dispatch['url'].split( ':' ).first
|
222
|
+
expect(d2.dispatch(strategy: :horizontal )['url'].split( ':' ).first).to eq(preferred)
|
223
|
+
expect(%W{127.0.0.1 127.0.0.3}).to include d3.dispatch(strategy: :horizontal )['url'].split( ':' ).first
|
224
|
+
expect(%W{127.0.0.2 127.0.0.3}).to include d3.dispatch(strategy: :horizontal )['url'].split( ':' ).first
|
225
|
+
expect(%W{127.0.0.2 127.0.0.3}).to include d1.dispatch(strategy: :horizontal )['url'].split( ':' ).first
|
226
|
+
end
|
165
227
|
end
|
166
228
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
229
|
+
context :vertical do
|
230
|
+
it 'provides Instances from the most burdened Dispatcher' do
|
231
|
+
d1 = dispatcher_spawn(
|
232
|
+
address: '127.0.0.1',
|
233
|
+
application: "#{fixtures_path}/mock_app.rb"
|
234
|
+
)
|
172
235
|
|
173
|
-
|
174
|
-
|
236
|
+
3.times do
|
237
|
+
d1.dispatch( load_balance: false )
|
238
|
+
end
|
239
|
+
|
240
|
+
d2 = dispatcher_spawn(
|
241
|
+
address: '127.0.0.2',
|
242
|
+
neighbour: d1.url,
|
243
|
+
application: "#{fixtures_path}/mock_app.rb"
|
244
|
+
)
|
245
|
+
|
246
|
+
2.times do
|
247
|
+
d2.dispatch( load_balance: false )
|
248
|
+
end
|
249
|
+
|
250
|
+
d3 = dispatcher_spawn(
|
251
|
+
address: '127.0.0.3',
|
252
|
+
neighbour: d1.url,
|
253
|
+
application: "#{fixtures_path}/mock_app.rb"
|
254
|
+
)
|
255
|
+
d3.dispatch( load_balance: false )
|
256
|
+
|
257
|
+
preferred = d1.url.split( ':' ).first
|
258
|
+
expect(d3.dispatch( strategy: :vertical )['url'].split( ':' ).first).to eq(preferred)
|
259
|
+
end
|
175
260
|
end
|
176
261
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
262
|
+
context 'default' do
|
263
|
+
it 'provides Instances from the least burdened Dispatcher' do
|
264
|
+
d1 = dispatcher_spawn(
|
265
|
+
address: '127.0.0.1',
|
266
|
+
application: "#{fixtures_path}/mock_app.rb"
|
267
|
+
)
|
268
|
+
|
269
|
+
3.times do
|
270
|
+
d1.dispatch( load_balance: false )
|
271
|
+
end
|
272
|
+
|
273
|
+
d2 = dispatcher_spawn(
|
274
|
+
address: '127.0.0.2',
|
275
|
+
neighbour: d1.url,
|
276
|
+
application: "#{fixtures_path}/mock_app.rb"
|
277
|
+
)
|
278
|
+
|
279
|
+
2.times do
|
280
|
+
d2.dispatch( load_balance: false )
|
281
|
+
end
|
282
|
+
|
283
|
+
d3 = dispatcher_spawn(
|
284
|
+
address: '127.0.0.3',
|
285
|
+
neighbour: d1.url,
|
286
|
+
application: "#{fixtures_path}/mock_app.rb"
|
287
|
+
)
|
288
|
+
d3.dispatch( load_balance: false )
|
289
|
+
preferred = d3.url.split( ':' ).first
|
290
|
+
|
291
|
+
expect(d3.dispatch['url'].split( ':' ).first).to eq(preferred)
|
292
|
+
expect(%W{127.0.0.3 127.0.0.2}).to include d1.dispatch['url'].split( ':' ).first
|
293
|
+
expect(d2.dispatch['url'].split( ':' ).first).to eq(preferred)
|
294
|
+
expect(%W{127.0.0.1 127.0.0.3}).to include d3.dispatch['url'].split( ':' ).first
|
295
|
+
expect(%W{127.0.0.2 127.0.0.3}).to include d3.dispatch['url'].split( ':' ).first
|
296
|
+
expect(%W{127.0.0.2 127.0.0.3}).to include d1.dispatch['url'].split( ':' ).first
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context 'other' do
|
301
|
+
it 'returns :error_unknown_strategy' do
|
302
|
+
expect(dispatcher_spawn( neighbour: subject.url ).
|
303
|
+
dispatch( strategy: 'blah' )).to eq('error_unknown_strategy')
|
304
|
+
end
|
305
|
+
end
|
191
306
|
end
|
192
307
|
|
193
308
|
context 'when the load-balance option is set to false' do
|
@@ -0,0 +1,6 @@
|
|
1
|
+
[Mon Jan 24 14:40:16 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:40:16 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:40:16 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:40:16 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:40:16 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:40:16 2022] [status] Ready
|
@@ -0,0 +1,6 @@
|
|
1
|
+
[Mon Jan 24 14:42:22 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:22 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:22 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:22 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:22 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:22 2022] [status] Ready
|
@@ -0,0 +1,6 @@
|
|
1
|
+
[Mon Jan 24 14:42:23 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:23 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:23 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:23 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:23 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:23 2022] [status] Ready
|
@@ -0,0 +1,6 @@
|
|
1
|
+
[Mon Jan 24 14:42:26 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:26 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:26 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:26 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:26 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:26 2022] [status] Ready
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[Mon Jan 24 14:42:27 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:27 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:27 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:27 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:27 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:27 2022] [status] Ready
|
7
|
+
[Mon Jan 24 14:42:27 2022] [status] Adding neighbour: 127.0.0.1:55183
|
8
|
+
[Mon Jan 24 14:42:27 2022] [info] Updated neighbours:
|
9
|
+
[Mon Jan 24 14:42:27 2022] [info] ---- 127.0.0.1:55183
|
10
|
+
[Mon Jan 24 14:42:27 2022] [status] Advertising: 127.0.0.1:55183
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[Mon Jan 24 14:42:27 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:27 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:27 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:27 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:27 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:27 2022] [status] Ready
|
7
|
+
[Mon Jan 24 14:42:27 2022] [status] Adding neighbour: 127.0.0.1:5750
|
8
|
+
[Mon Jan 24 14:42:27 2022] [info] Updated neighbours:
|
9
|
+
[Mon Jan 24 14:42:27 2022] [info] ---- 127.0.0.1:5750
|
10
|
+
[Mon Jan 24 14:42:27 2022] [status] Advertising: 127.0.0.1:5750
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[Mon Jan 24 14:42:29 2022] [status] Starting the RPC Server...
|
2
|
+
[Mon Jan 24 14:42:29 2022] [status] Initializing grid node...
|
3
|
+
[Mon Jan 24 14:42:29 2022] [status] Node ready.
|
4
|
+
[Mon Jan 24 14:42:29 2022] [info] Updated neighbours:
|
5
|
+
[Mon Jan 24 14:42:29 2022] [info] <empty>
|
6
|
+
[Mon Jan 24 14:42:29 2022] [status] Ready
|
7
|
+
[Mon Jan 24 14:42:29 2022] [status] Adding neighbour: 127.0.0.1:44327
|
8
|
+
[Mon Jan 24 14:42:29 2022] [info] Updated neighbours:
|
9
|
+
[Mon Jan 24 14:42:29 2022] [info] ---- 127.0.0.1:44327
|
10
|
+
[Mon Jan 24 14:42:29 2022] [status] Advertising: 127.0.0.1:44327
|