background_queue 0.2.0
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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/.rvmrc +48 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +20 -0
- data/README.md +69 -0
- data/Rakefile +42 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/background_queue.gemspec +158 -0
- data/bin/bg_queue +26 -0
- data/lib/background_queue.rb +8 -0
- data/lib/background_queue/client.rb +96 -0
- data/lib/background_queue/client_lib/command.rb +36 -0
- data/lib/background_queue/client_lib/config.rb +109 -0
- data/lib/background_queue/client_lib/connection.rb +105 -0
- data/lib/background_queue/client_lib/job_handle.rb +19 -0
- data/lib/background_queue/command.rb +49 -0
- data/lib/background_queue/config.rb +118 -0
- data/lib/background_queue/server_lib/balanced_queue.rb +108 -0
- data/lib/background_queue/server_lib/config.rb +339 -0
- data/lib/background_queue/server_lib/event_connection.rb +133 -0
- data/lib/background_queue/server_lib/event_server.rb +35 -0
- data/lib/background_queue/server_lib/job.rb +252 -0
- data/lib/background_queue/server_lib/job_registry.rb +30 -0
- data/lib/background_queue/server_lib/lru.rb +193 -0
- data/lib/background_queue/server_lib/owner.rb +54 -0
- data/lib/background_queue/server_lib/priority_queue.rb +156 -0
- data/lib/background_queue/server_lib/queue_registry.rb +123 -0
- data/lib/background_queue/server_lib/server.rb +314 -0
- data/lib/background_queue/server_lib/sorted_workers.rb +52 -0
- data/lib/background_queue/server_lib/task.rb +79 -0
- data/lib/background_queue/server_lib/task_registry.rb +51 -0
- data/lib/background_queue/server_lib/thread_manager.rb +121 -0
- data/lib/background_queue/server_lib/worker.rb +18 -0
- data/lib/background_queue/server_lib/worker_balancer.rb +97 -0
- data/lib/background_queue/server_lib/worker_client.rb +94 -0
- data/lib/background_queue/server_lib/worker_thread.rb +70 -0
- data/lib/background_queue/utils.rb +40 -0
- data/lib/background_queue/worker/base.rb +46 -0
- data/lib/background_queue/worker/calling.rb +59 -0
- data/lib/background_queue/worker/config.rb +35 -0
- data/lib/background_queue/worker/environment.rb +70 -0
- data/lib/background_queue/worker/worker_loader.rb +94 -0
- data/lib/background_queue_server.rb +21 -0
- data/lib/background_queue_worker.rb +5 -0
- data/spec/background_queue/client_lib/command_spec.rb +75 -0
- data/spec/background_queue/client_lib/config_spec.rb +156 -0
- data/spec/background_queue/client_lib/connection_spec.rb +170 -0
- data/spec/background_queue/client_spec.rb +95 -0
- data/spec/background_queue/command_spec.rb +34 -0
- data/spec/background_queue/config_spec.rb +134 -0
- data/spec/background_queue/server_lib/balanced_queue_spec.rb +122 -0
- data/spec/background_queue/server_lib/config_spec.rb +443 -0
- data/spec/background_queue/server_lib/event_connection_spec.rb +190 -0
- data/spec/background_queue/server_lib/event_server_spec.rb +48 -0
- data/spec/background_queue/server_lib/integration/full_test_spec.rb +247 -0
- data/spec/background_queue/server_lib/integration/queue_integration_spec.rb +98 -0
- data/spec/background_queue/server_lib/integration/serialize_spec.rb +127 -0
- data/spec/background_queue/server_lib/job_registry_spec.rb +65 -0
- data/spec/background_queue/server_lib/job_spec.rb +525 -0
- data/spec/background_queue/server_lib/owner_spec.rb +33 -0
- data/spec/background_queue/server_lib/priority_queue_spec.rb +182 -0
- data/spec/background_queue/server_lib/server_spec.rb +353 -0
- data/spec/background_queue/server_lib/sorted_workers_spec.rb +122 -0
- data/spec/background_queue/server_lib/task_registry_spec.rb +69 -0
- data/spec/background_queue/server_lib/task_spec.rb +20 -0
- data/spec/background_queue/server_lib/thread_manager_spec.rb +106 -0
- data/spec/background_queue/server_lib/worker_balancer_spec.rb +127 -0
- data/spec/background_queue/server_lib/worker_client_spec.rb +196 -0
- data/spec/background_queue/server_lib/worker_thread_spec.rb +125 -0
- data/spec/background_queue/utils_spec.rb +27 -0
- data/spec/background_queue/worker/base_spec.rb +35 -0
- data/spec/background_queue/worker/calling_spec.rb +103 -0
- data/spec/background_queue/worker/environment_spec.rb +67 -0
- data/spec/background_queue/worker/worker_loader_spec.rb +103 -0
- data/spec/background_queue_spec.rb +7 -0
- data/spec/resources/config-client.yml +7 -0
- data/spec/resources/config-serialize.yml +12 -0
- data/spec/resources/config.yml +12 -0
- data/spec/resources/example_worker.rb +4 -0
- data/spec/resources/example_worker_with_error.rb +4 -0
- data/spec/resources/test_worker.rb +8 -0
- data/spec/shared/queue_registry_shared.rb +216 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/default_task.rb +9 -0
- data/spec/support/private.rb +23 -0
- data/spec/support/simple_server.rb +28 -0
- data/spec/support/simple_task.rb +58 -0
- data/spec/support/test_worker_server.rb +205 -0
- metadata +254 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'background_queue'
|
3
|
+
|
4
|
+
describe "Command" do
|
5
|
+
|
6
|
+
context "add_task" do
|
7
|
+
it "creates valid command" do
|
8
|
+
cmd = BackgroundQueue::ClientLib::Command.add_task_command(:worker, :owner_id, :job_id, :task_id, 1, {:a=>:b}, {:c=>:d} )
|
9
|
+
cmd.code.should eq(:add_task)
|
10
|
+
cmd.options[:c].should eq(:d)
|
11
|
+
cmd.args[:worker].should eq(:worker)
|
12
|
+
cmd.args[:owner_id].should eq(:owner_id)
|
13
|
+
cmd.args[:job_id].should eq(:job_id)
|
14
|
+
cmd.args[:task_id].should eq(:task_id)
|
15
|
+
cmd.args[:params][:a].should eq(:b)
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "add_tasks" do
|
21
|
+
it "creates valid command" do
|
22
|
+
cmd = BackgroundQueue::ClientLib::Command.add_tasks_command(:worker, :owner_id, :job_id, [[:task1_id, {:a=>:b}], [:task2_id, {:e=>:f}]], 1, {:shared=>:param}, {:c=>:d} )
|
23
|
+
cmd.code.should eq(:add_tasks)
|
24
|
+
cmd.options[:c].should eq(:d)
|
25
|
+
cmd.args[:worker].should eq(:worker)
|
26
|
+
cmd.args[:owner_id].should eq(:owner_id)
|
27
|
+
cmd.args[:job_id].should eq(:job_id)
|
28
|
+
cmd.args[:shared_parameters][:shared].should eq(:param)
|
29
|
+
cmd.args[:tasks].length.should eq(2)
|
30
|
+
cmd.args[:tasks].first.length.should eq(2)
|
31
|
+
cmd.args[:tasks].first[0].should eq(:task1_id)
|
32
|
+
cmd.args[:tasks].first[1][:a].should eq(:b)
|
33
|
+
cmd.args[:tasks].last.length.should eq(2)
|
34
|
+
cmd.args[:tasks].last[0].should eq(:task2_id)
|
35
|
+
cmd.args[:tasks].last[1][:e].should eq(:f)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "fails if no tasks are defined" do
|
39
|
+
expect {
|
40
|
+
cmd = BackgroundQueue::ClientLib::Command.add_tasks_command(:worker, :owner_id, :job_id, [], 1, {:shared=>:param}, {:c=>:d} )
|
41
|
+
}.to raise_exception(BackgroundQueue::InvalidCommand, "No Tasks In List")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
context "#get_status_command" do
|
47
|
+
it "creates valid command" do
|
48
|
+
cmd = BackgroundQueue::ClientLib::Command.get_status_command(:job_id, {:c=>:d} )
|
49
|
+
cmd.code.should eq(:get_status)
|
50
|
+
cmd.options[:c].should eq(:d)
|
51
|
+
cmd.args[:job_id].should eq(:job_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
#i cant see why this would be needed.... will add back if needed
|
57
|
+
#context "remove_tasks" do
|
58
|
+
# it "creates valid command" do
|
59
|
+
# cmd = BackgroundQueue::ClientLib::Command.remove_tasks_command([:task1_id,:task2_id], {:c=>:d} )
|
60
|
+
# cmd.code.should eq(:remove_tasks)
|
61
|
+
# cmd.options[:c].should eq(:d)
|
62
|
+
# cmd.args[:tasks].length.should eq(2)
|
63
|
+
# cmd.args[:tasks][0].should eq(:task1_id)
|
64
|
+
# cmd.args[:tasks][1].should eq(:task2_id)
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# it "fails if no tasks are defined" do
|
68
|
+
# expect {
|
69
|
+
# cmd = BackgroundQueue::ClientLib::Command.remove_tasks_command([], {:c=>:d} )
|
70
|
+
# }.to raise_exception(BackgroundQueue::InvalidCommand, "No Tasks In List")
|
71
|
+
# end
|
72
|
+
#end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'background_queue'
|
3
|
+
|
4
|
+
unless defined? Rails
|
5
|
+
module Rails; end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Client Config" do
|
9
|
+
|
10
|
+
context "using map" do
|
11
|
+
context "loading server entry" do
|
12
|
+
it "creates a server entry if all required string fields exist" do
|
13
|
+
entry = BackgroundQueue::ClientLib::Config::Server.new({
|
14
|
+
'host'=>"127.0.0.1",
|
15
|
+
'port'=>85
|
16
|
+
})
|
17
|
+
entry.host.should eq("127.0.0.1")
|
18
|
+
entry.port.should eq(85)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "creates a server entry if all required symbol fields exist" do
|
22
|
+
entry = BackgroundQueue::ClientLib::Config::Server.new({
|
23
|
+
:host=>"127.0.0.1",
|
24
|
+
:port=>85
|
25
|
+
})
|
26
|
+
entry.host.should eq("127.0.0.1")
|
27
|
+
entry.port.should eq(85)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "creates a server entry using default port" do
|
31
|
+
entry = BackgroundQueue::ClientLib::Config::Server.new({
|
32
|
+
:host=>"127.0.0.1"
|
33
|
+
})
|
34
|
+
entry.host.should eq("127.0.0.1")
|
35
|
+
entry.port.should eq(BackgroundQueue::ClientLib::Config::DEFAULT_PORT)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "errors if missing or invalid hostname on server entry" do
|
39
|
+
expect {
|
40
|
+
BackgroundQueue::ClientLib::Config::Server.new({})
|
41
|
+
}.to raise_error(
|
42
|
+
BackgroundQueue::LoadError,
|
43
|
+
"Missing 'host' configuration entry"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "errors if invalid type" do
|
48
|
+
expect {
|
49
|
+
BackgroundQueue::ClientLib::Config::Server.new([])
|
50
|
+
}.to raise_error(
|
51
|
+
BackgroundQueue::LoadError,
|
52
|
+
"Invalid data type (Array), expecting Hash"
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "loading primary server entry" do
|
58
|
+
before do
|
59
|
+
File.stub(:expand_path) { :expanded_path }
|
60
|
+
end
|
61
|
+
|
62
|
+
it "creates primary server entry" do
|
63
|
+
entry = BackgroundQueue::ClientLib::Config.__prv__build_primary_server_entry({ 'server'=> { :host=>"127.0.0.1" }}, :path_that_exists)
|
64
|
+
entry.host.should eq("127.0.0.1")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "errors if missing" do
|
68
|
+
expect {
|
69
|
+
BackgroundQueue::ClientLib::Config.__prv__build_primary_server_entry({}, :path_that_exists)
|
70
|
+
}.to raise_error(
|
71
|
+
BackgroundQueue::LoadError,
|
72
|
+
"Missing 'server' entry in background queue configuration file expanded_path"
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "errors if invalid" do
|
77
|
+
expect {
|
78
|
+
BackgroundQueue::ClientLib::Config.__prv__build_primary_server_entry({:server=> {}}, :path_that_exists)
|
79
|
+
}.to raise_error(
|
80
|
+
BackgroundQueue::LoadError,
|
81
|
+
"Error loading 'server' entry from background queue configuration file expanded_path: Missing 'host' configuration entry"
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "loading failover server entries" do
|
87
|
+
|
88
|
+
it "creates failover server entries if defined" do
|
89
|
+
entries = BackgroundQueue::ClientLib::Config.__prv__build_failover_server_entries({ :failover=> [{ :host=>"127.0.0.1" }, { :host=>"127.0.0.2" }]}, :path_that_exists)
|
90
|
+
entries.length.should eq(2)
|
91
|
+
entries.first.host.should eq("127.0.0.1")
|
92
|
+
entries.last.host.should eq("127.0.0.2")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "errors if failover entry is invalid" do
|
96
|
+
File.stub(:expand_path) { :expanded_path }
|
97
|
+
expect {
|
98
|
+
BackgroundQueue::ClientLib::Config.__prv__build_failover_server_entries({ 'failover'=> [{ :host=>"127.0.0.1" }, { }]}, :path_that_exists)
|
99
|
+
}.to raise_error(
|
100
|
+
BackgroundQueue::LoadError,
|
101
|
+
"Error loading 'failover' entry (2) from background queue configuration file expanded_path: Missing 'host' configuration entry"
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
context "creating Config entry" do
|
110
|
+
before do
|
111
|
+
File.stub(:expand_path) { :expanded_path }
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should create Config instance" do
|
115
|
+
config = BackgroundQueue::ClientLib::Config.load_hash({
|
116
|
+
:server=>{:host=>"127.0.0.1"},
|
117
|
+
:failover=>[{:host=>"127.0.0.2"}, {:host=>"127.0.0.3"}],
|
118
|
+
:memcache=> "127.0.0.1:4000"
|
119
|
+
}, :path_that_exists)
|
120
|
+
config.server.host.should eq("127.0.0.1")
|
121
|
+
config.failover.length.should eq(2)
|
122
|
+
config.failover.first.host.should eq("127.0.0.2")
|
123
|
+
config.failover.last.host.should eq("127.0.0.3")
|
124
|
+
config.memcache.length.should eq(1)
|
125
|
+
config.memcache.first.should eq('127.0.0.1:4000')
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should fail when missing server" do
|
129
|
+
expect {
|
130
|
+
config = BackgroundQueue::ClientLib::Config.load_hash({ }, :path_that_exists)
|
131
|
+
}.to raise_error(
|
132
|
+
BackgroundQueue::LoadError,
|
133
|
+
"Missing 'server' entry in background queue configuration file expanded_path"
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should fail when missing memcache" do
|
138
|
+
expect {
|
139
|
+
config = BackgroundQueue::ClientLib::Config.load_hash({ :server=>{:host=>"127.0.0.1"} }, :path_that_exists)
|
140
|
+
}.to raise_error(
|
141
|
+
BackgroundQueue::LoadError,
|
142
|
+
"Missing 'memcache' entry in configuration file expanded_path"
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not fail when missing failover" do
|
147
|
+
config = BackgroundQueue::ClientLib::Config.load_hash({
|
148
|
+
:server=>{:host=>"127.0.0.1"},
|
149
|
+
:memcache=> "127.0.0.1:4000"
|
150
|
+
}, :path_that_exists)
|
151
|
+
config.failover.length.should eq(0)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'background_queue'
|
3
|
+
|
4
|
+
describe "Connection" do
|
5
|
+
|
6
|
+
let(:server) {
|
7
|
+
svr = double('Server')
|
8
|
+
svr.stub({:host=>:host, :port=>:port})
|
9
|
+
svr
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
context "connecting" do
|
15
|
+
|
16
|
+
subject { BackgroundQueue::ClientLib::Connection.new(:client, server) }
|
17
|
+
|
18
|
+
it "can successfully connect" do
|
19
|
+
TCPSocket.should_receive(:open).with(:host, :port) { :socket }
|
20
|
+
subject.__prv__connect.should eq(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "fails when no server to connect to" do
|
24
|
+
TCPSocket.should_receive(:open).with(:host, :port) { raise "Unable to connect" }
|
25
|
+
expect { subject.__prv__connect }.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Error Connecting to host:port: Unable to connect")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "fails if connection times out" do
|
29
|
+
Timeout.should_receive(:timeout).with(any_args) { raise Timeout::Error }
|
30
|
+
expect { subject.__prv__connect }.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Timeout Connecting to host:port")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "connected" do
|
35
|
+
|
36
|
+
let(:socket) { stub() }
|
37
|
+
|
38
|
+
subject {
|
39
|
+
s = BackgroundQueue::ClientLib::Connection.new(:client, server)
|
40
|
+
TCPSocket.should_receive(:open).with(:host, :port) { socket }
|
41
|
+
s.__prv__connect
|
42
|
+
s
|
43
|
+
}
|
44
|
+
|
45
|
+
context "sending data" do
|
46
|
+
|
47
|
+
it "can send data successfully in one go" do
|
48
|
+
buf = "some data"
|
49
|
+
socket.should_receive(:write).with(buf) { buf.length }
|
50
|
+
subject.__prv__send_data(buf).should eq(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "can send data successfully in 3 goes" do
|
54
|
+
buf = "12345678"
|
55
|
+
socket.should_receive(:write).with("12345678") { 2 }
|
56
|
+
socket.should_receive(:write).with("345678") { 3 }
|
57
|
+
socket.should_receive(:write).with("678") { 3 }
|
58
|
+
subject.__prv__send_data(buf).should eq(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "fails when underlying network fails" do
|
62
|
+
buf = "12345678"
|
63
|
+
socket.should_receive(:write).with("12345678") { 2 }
|
64
|
+
socket.should_receive(:write).with("345678") { raise "Socket Disconnected" }
|
65
|
+
|
66
|
+
expect { subject.__prv__send_data(buf)}.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Error Sending to host:port: Socket Disconnected")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "fails when command times out" do
|
70
|
+
init_subject = subject #need to init the subject before forcing timeout
|
71
|
+
Timeout.should_receive(:timeout).with(any_args) { raise Timeout::Error }
|
72
|
+
expect { init_subject.__prv__send_data("data")}.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Timeout Sending to host:port")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "sending with header" do
|
77
|
+
|
78
|
+
let(:data) { "data"}
|
79
|
+
let(:packed_data) { [1,4,data].pack("SLZ4") }
|
80
|
+
|
81
|
+
it "can pack the header onto the data" do
|
82
|
+
BackgroundQueue::ClientLib::Connection.add_header(data).should eq(packed_data)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "can send data with header" do
|
86
|
+
subject.should_receive(:send_data).with(packed_data) { true}
|
87
|
+
subject.__prv__send_with_header(data).should eq(true)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context "receiving data" do
|
93
|
+
it "can receive data successfully in one go" do
|
94
|
+
socket.should_receive(:recvfrom).with(4) { ["data", nil] }
|
95
|
+
subject.__prv__receive_data(4).should eq("data")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "can receive data successfully in 3 goes" do
|
99
|
+
socket.should_receive(:recvfrom).with(10) { ["0123", nil] }
|
100
|
+
socket.should_receive(:recvfrom).with(6) { ["45", nil] }
|
101
|
+
socket.should_receive(:recvfrom).with(4) { ["6789", nil] }
|
102
|
+
subject.__prv__receive_data(10).should eq("0123456789")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "fails when underlying network fails" do
|
106
|
+
socket.should_receive(:recvfrom).with(10) { ["0123", nil] }
|
107
|
+
socket.should_receive(:recvfrom).with(6) { raise "Socket Disconnected" }
|
108
|
+
expect { subject.__prv__receive_data(10)}.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Error Receiving 10 bytes from host:port: Socket Disconnected")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "fails when response times out" do
|
112
|
+
init_subject = subject #need to init the subject before forcing timeout
|
113
|
+
Timeout.should_receive(:timeout).with(any_args) { raise Timeout::Error }
|
114
|
+
expect { init_subject.__prv__receive_data(10)}.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Timeout Receiving 10 bytes from host:port")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "receiving with header" do
|
119
|
+
|
120
|
+
let(:data) { "data"}
|
121
|
+
let(:packed_data) { [1,4,data].pack("SLZ4") }
|
122
|
+
|
123
|
+
|
124
|
+
it "can receive data with header" do
|
125
|
+
subject.should_receive(:receive_data).with(6) { packed_data[0,6] }
|
126
|
+
subject.should_receive(:receive_data).with(4) { packed_data[6,4] }
|
127
|
+
|
128
|
+
subject.__prv__receive_with_header().should eq(data)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
context "sending command" do
|
136
|
+
|
137
|
+
subject { BackgroundQueue::ClientLib::Connection.new(:client, server) }
|
138
|
+
let(:send_command) { stub({:to_buf=>:data}) }
|
139
|
+
|
140
|
+
it "can successfully send command" do
|
141
|
+
|
142
|
+
subject.stub(:check_connected) { true }
|
143
|
+
subject.should_receive(:send_with_header).with(:data) { true }
|
144
|
+
subject.should_receive(:receive_with_header).with(no_args) { :receive_response }
|
145
|
+
BackgroundQueue::Command.should_receive(:from_buf).with(:receive_response) { :command_response }
|
146
|
+
|
147
|
+
subject.send_command(send_command).should eq(:command_response)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "fails if unable to connect" do
|
151
|
+
TCPSocket.should_receive(:open).with(:host, :port) { raise "Unable to connect" }
|
152
|
+
expect { subject.send_command(send_command) }.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Error Connecting to host:port: Unable to connect")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "fails if unable to send data" do
|
156
|
+
subject.stub(:check_connected) { true }
|
157
|
+
subject.should_receive(:send_with_header).with(:data) { raise BackgroundQueue::ClientLib::ConnectionError, "Send Error" }
|
158
|
+
expect { subject.send_command(send_command) }.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Send Error")
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
it "fails if unable to recieve response" do
|
163
|
+
subject.stub(:check_connected) { true }
|
164
|
+
subject.should_receive(:send_with_header).with(:data) { true }
|
165
|
+
subject.should_receive(:receive_with_header).with(no_args) { raise BackgroundQueue::ClientLib::ConnectionError, "Receive Error" }
|
166
|
+
expect { subject.send_command(send_command) }.to raise_error(BackgroundQueue::ClientLib::ConnectionError, "Receive Error")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'background_queue'
|
3
|
+
|
4
|
+
describe "Client" do
|
5
|
+
|
6
|
+
context "initializing" do
|
7
|
+
it "loads from config path" do
|
8
|
+
BackgroundQueue::ClientLib::Config.stub(:load_file).with(:path_that_exists) { BackgroundQueue::ClientLib::Config.new(:a, :b, :c) }
|
9
|
+
bq_client = BackgroundQueue::Client.new(:path_that_exists)
|
10
|
+
bq_client.config.server.should eq(:a)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "initialized" do
|
15
|
+
subject {
|
16
|
+
BackgroundQueue::ClientLib::Config.stub(:load_file).with(:path_that_exists) {
|
17
|
+
BackgroundQueue::ClientLib::Config.new(:primary_server, [:failover_1, :failover_2], :memcache_server)
|
18
|
+
}
|
19
|
+
BackgroundQueue::Client.new(:path_that_exists)
|
20
|
+
}
|
21
|
+
|
22
|
+
context "sending a command" do
|
23
|
+
it "can send a command to a server" do
|
24
|
+
BackgroundQueue::ClientLib::Connection.any_instance.should_receive(:send_command).with(:command) { true }
|
25
|
+
subject.__prv__send_command_to_server(:command, :primary_server).should eq([true, :primary_server])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can succeed first time" do
|
29
|
+
subject.should_receive(:send_command_to_server).with(:command, :primary_server) { true }
|
30
|
+
subject.__prv__send_command(:command).should eq(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can use failover server if main server fails" do
|
34
|
+
subject.should_receive(:send_command_to_server).with(:command, :primary_server) { raise BackgroundQueue::ClientLib::ConnectionError, "Primary" }
|
35
|
+
subject.should_receive(:send_command_to_server).with(:command, :failover_1) { true }
|
36
|
+
subject.__prv__send_command(:command).should eq(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "can use second failover server if needed" do
|
40
|
+
subject.should_receive(:send_command_to_server).with(:command, :primary_server) { raise BackgroundQueue::ClientLib::ConnectionError, "Primary" }
|
41
|
+
subject.should_receive(:send_command_to_server).with(:command, :failover_1) { raise BackgroundQueue::ClientLib::ConnectionError, "Failure 1" }
|
42
|
+
subject.should_receive(:send_command_to_server).with(:command, :failover_2) { true }
|
43
|
+
subject.__prv__send_command(:command).should eq(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "throws an exception if all connections fail" do
|
47
|
+
subject.should_receive(:send_command_to_server).with(:command, :primary_server) { raise BackgroundQueue::ClientLib::ConnectionError, "Primary" }
|
48
|
+
subject.should_receive(:send_command_to_server).with(:command, :failover_1) { raise BackgroundQueue::ClientLib::ConnectionError, "Failure 1" }
|
49
|
+
subject.should_receive(:send_command_to_server).with(:command, :failover_2) { raise BackgroundQueue::ClientLib::ConnectionError, "Failure 2" }
|
50
|
+
expect { subject.__prv__send_command(:command) }.to raise_error(BackgroundQueue::ClientException, "Primary, Attempt 2: Failure 1, Attempt 3: Failure 2")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "single call commands" do
|
55
|
+
before do
|
56
|
+
subject.should_receive(:send_command).with(any_args) { [true, :server] }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "#add_task" do
|
60
|
+
it "can build and send an add task command" do
|
61
|
+
job_handle = subject.add_task(:worker, :owner_id, :job_id, :task_id, 1, {}, {} )
|
62
|
+
job_handle.owner_id.should eq(:owner_id)
|
63
|
+
job_handle.job_id.should eq(:job_id)
|
64
|
+
job_handle.server.should eq(:server)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "will dynamically generate a job id/task id if not passed" do
|
68
|
+
subject.should_receive(:generate_ids).and_return([:jjj, :ttt])
|
69
|
+
job_handle = subject.add_task(:worker, :owner_id, nil, nil, 1, {}, {} )
|
70
|
+
job_handle.job_id.should eq(:jjj)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can build and send an add tasks command" do
|
75
|
+
subject.add_tasks(:worker, :owner_id, :job_id, :tasks, 1, {}, {} ).should eq([true, :server])
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
#it "can build and send a remove task command" do
|
80
|
+
# subject.remove_tasks(:tasks, {}).should eq(true)
|
81
|
+
#end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
context "#get_status" do
|
87
|
+
it "passes the requested server" do
|
88
|
+
job_handle = double("jh", :server=>:another_server, :job_id=>:job_id)
|
89
|
+
BackgroundQueue::ClientLib::Command.should_receive(:get_status_command).with(:job_id, {} ).and_return(:cmd)
|
90
|
+
subject.should_receive(:send_command).with(:cmd, :another_server) { [true, :another_server] }
|
91
|
+
subject.get_status(job_handle, {}).should eq(true)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|