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.
Files changed (91) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +48 -0
  4. data/Gemfile +19 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +69 -0
  7. data/Rakefile +42 -0
  8. data/TODO +2 -0
  9. data/VERSION +1 -0
  10. data/background_queue.gemspec +158 -0
  11. data/bin/bg_queue +26 -0
  12. data/lib/background_queue.rb +8 -0
  13. data/lib/background_queue/client.rb +96 -0
  14. data/lib/background_queue/client_lib/command.rb +36 -0
  15. data/lib/background_queue/client_lib/config.rb +109 -0
  16. data/lib/background_queue/client_lib/connection.rb +105 -0
  17. data/lib/background_queue/client_lib/job_handle.rb +19 -0
  18. data/lib/background_queue/command.rb +49 -0
  19. data/lib/background_queue/config.rb +118 -0
  20. data/lib/background_queue/server_lib/balanced_queue.rb +108 -0
  21. data/lib/background_queue/server_lib/config.rb +339 -0
  22. data/lib/background_queue/server_lib/event_connection.rb +133 -0
  23. data/lib/background_queue/server_lib/event_server.rb +35 -0
  24. data/lib/background_queue/server_lib/job.rb +252 -0
  25. data/lib/background_queue/server_lib/job_registry.rb +30 -0
  26. data/lib/background_queue/server_lib/lru.rb +193 -0
  27. data/lib/background_queue/server_lib/owner.rb +54 -0
  28. data/lib/background_queue/server_lib/priority_queue.rb +156 -0
  29. data/lib/background_queue/server_lib/queue_registry.rb +123 -0
  30. data/lib/background_queue/server_lib/server.rb +314 -0
  31. data/lib/background_queue/server_lib/sorted_workers.rb +52 -0
  32. data/lib/background_queue/server_lib/task.rb +79 -0
  33. data/lib/background_queue/server_lib/task_registry.rb +51 -0
  34. data/lib/background_queue/server_lib/thread_manager.rb +121 -0
  35. data/lib/background_queue/server_lib/worker.rb +18 -0
  36. data/lib/background_queue/server_lib/worker_balancer.rb +97 -0
  37. data/lib/background_queue/server_lib/worker_client.rb +94 -0
  38. data/lib/background_queue/server_lib/worker_thread.rb +70 -0
  39. data/lib/background_queue/utils.rb +40 -0
  40. data/lib/background_queue/worker/base.rb +46 -0
  41. data/lib/background_queue/worker/calling.rb +59 -0
  42. data/lib/background_queue/worker/config.rb +35 -0
  43. data/lib/background_queue/worker/environment.rb +70 -0
  44. data/lib/background_queue/worker/worker_loader.rb +94 -0
  45. data/lib/background_queue_server.rb +21 -0
  46. data/lib/background_queue_worker.rb +5 -0
  47. data/spec/background_queue/client_lib/command_spec.rb +75 -0
  48. data/spec/background_queue/client_lib/config_spec.rb +156 -0
  49. data/spec/background_queue/client_lib/connection_spec.rb +170 -0
  50. data/spec/background_queue/client_spec.rb +95 -0
  51. data/spec/background_queue/command_spec.rb +34 -0
  52. data/spec/background_queue/config_spec.rb +134 -0
  53. data/spec/background_queue/server_lib/balanced_queue_spec.rb +122 -0
  54. data/spec/background_queue/server_lib/config_spec.rb +443 -0
  55. data/spec/background_queue/server_lib/event_connection_spec.rb +190 -0
  56. data/spec/background_queue/server_lib/event_server_spec.rb +48 -0
  57. data/spec/background_queue/server_lib/integration/full_test_spec.rb +247 -0
  58. data/spec/background_queue/server_lib/integration/queue_integration_spec.rb +98 -0
  59. data/spec/background_queue/server_lib/integration/serialize_spec.rb +127 -0
  60. data/spec/background_queue/server_lib/job_registry_spec.rb +65 -0
  61. data/spec/background_queue/server_lib/job_spec.rb +525 -0
  62. data/spec/background_queue/server_lib/owner_spec.rb +33 -0
  63. data/spec/background_queue/server_lib/priority_queue_spec.rb +182 -0
  64. data/spec/background_queue/server_lib/server_spec.rb +353 -0
  65. data/spec/background_queue/server_lib/sorted_workers_spec.rb +122 -0
  66. data/spec/background_queue/server_lib/task_registry_spec.rb +69 -0
  67. data/spec/background_queue/server_lib/task_spec.rb +20 -0
  68. data/spec/background_queue/server_lib/thread_manager_spec.rb +106 -0
  69. data/spec/background_queue/server_lib/worker_balancer_spec.rb +127 -0
  70. data/spec/background_queue/server_lib/worker_client_spec.rb +196 -0
  71. data/spec/background_queue/server_lib/worker_thread_spec.rb +125 -0
  72. data/spec/background_queue/utils_spec.rb +27 -0
  73. data/spec/background_queue/worker/base_spec.rb +35 -0
  74. data/spec/background_queue/worker/calling_spec.rb +103 -0
  75. data/spec/background_queue/worker/environment_spec.rb +67 -0
  76. data/spec/background_queue/worker/worker_loader_spec.rb +103 -0
  77. data/spec/background_queue_spec.rb +7 -0
  78. data/spec/resources/config-client.yml +7 -0
  79. data/spec/resources/config-serialize.yml +12 -0
  80. data/spec/resources/config.yml +12 -0
  81. data/spec/resources/example_worker.rb +4 -0
  82. data/spec/resources/example_worker_with_error.rb +4 -0
  83. data/spec/resources/test_worker.rb +8 -0
  84. data/spec/shared/queue_registry_shared.rb +216 -0
  85. data/spec/spec_helper.rb +15 -0
  86. data/spec/support/default_task.rb +9 -0
  87. data/spec/support/private.rb +23 -0
  88. data/spec/support/simple_server.rb +28 -0
  89. data/spec/support/simple_task.rb +58 -0
  90. data/spec/support/test_worker_server.rb +205 -0
  91. metadata +254 -0
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'background_queue_server'
3
+
4
+
5
+ describe BackgroundQueue::ServerLib::Owner do
6
+ let(:balancer_manager) {
7
+ p = double("bm")
8
+ p.stub(:register_job)
9
+ p
10
+ }
11
+ it_behaves_like "a queue registry" do
12
+
13
+ let(:new_instance) { BackgroundQueue::ServerLib::Owner.new(1, balancer_manager) }
14
+ end
15
+
16
+ context "callbacks" do
17
+
18
+ subject { BackgroundQueue::ServerLib::Owner.new(1, balancer_manager) }
19
+
20
+ it "gets the job_id from tasks" do
21
+ subject.__prv__get_queue_id_from_item(SimpleTask.new(:owner_id, :job_id, :task_id, 3)).should eq(:job_id)
22
+ end
23
+
24
+ it "calls add_item to add items to jobs" do
25
+ BackgroundQueue::ServerLib::Job.any_instance.should_receive(:add_item).with(:item)
26
+ subject.__prv__add_item_to_queue(BackgroundQueue::ServerLib::Job.new(1, balancer_manager), :item)
27
+ end
28
+
29
+ it "specifies the job class as its queue class" do
30
+ subject.class.queue_class.should eq(BackgroundQueue::ServerLib::Job)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,182 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'background_queue_server'
3
+
4
+
5
+ class SimpleItem
6
+ attr_accessor :id
7
+ attr_accessor :priority
8
+
9
+ def initialize(id, priority)
10
+ @id = id
11
+ @priority = priority
12
+ end
13
+ end
14
+
15
+
16
+ describe "Priority Queue" do
17
+
18
+ context "internal array of queues" do
19
+
20
+ subject { BackgroundQueue::ServerLib::PriorityQueue.new }
21
+
22
+ it "can insert queue entries" do
23
+
24
+ q1 = subject.__prv__insert_queue_at_index(1, 0)
25
+ q3 = subject.__prv__insert_queue_at_index(3, 1)
26
+ q2 = subject.__prv__insert_queue_at_index(2, 1)
27
+
28
+ subject.__prv__get_queues.should eq([q1, q2, q3])
29
+
30
+ end
31
+
32
+
33
+ it "can add a queue to the correct priority index" do
34
+ q3 = subject.__prv__get_queue_for_priority(3, true)
35
+
36
+ subject.__prv__get_queues.should eq([q3])
37
+
38
+ q2 = subject.__prv__get_queue_for_priority(2, true)
39
+ subject.__prv__get_queues.should eq([q2, q3])
40
+
41
+ q5 = subject.__prv__get_queue_for_priority(5, true)
42
+ subject.__prv__get_queues.should eq([q2, q3, q5])
43
+
44
+ q4 = subject.__prv__get_queue_for_priority(4, true)
45
+ subject.__prv__get_queues.should eq([q2, q3, q4, q5])
46
+ end
47
+
48
+ it "can get the next priority entry" do
49
+ subject.__prv__get_queue_for_priority(3, true)
50
+ q2 = subject.__prv__get_queue_for_priority(2, true)
51
+ subject.__prv__get_queue_for_priority(4, true)
52
+
53
+ subject.__prv__get_next_queue.should eq(q2)
54
+ end
55
+
56
+ it "can remove the queue entry" do
57
+
58
+ q3 = subject.__prv__get_queue_for_priority(3, true)
59
+ q2 = subject.__prv__get_queue_for_priority(2, true)
60
+ q5 = subject.__prv__get_queue_for_priority(5, true)
61
+ q4 = subject.__prv__get_queue_for_priority(4, true)
62
+
63
+ subject.__prv__get_queues.should eq([q2, q3, q4, q5])
64
+
65
+ subject.__prv__remove_queue(q3)
66
+ subject.__prv__get_queues.should eq([q2, q4, q5])
67
+
68
+ subject.__prv__remove_queue(q2)
69
+ subject.__prv__get_queues.should eq([q4, q5])
70
+
71
+ subject.__prv__remove_queue(q5)
72
+ subject.__prv__get_queues.should eq([q4])
73
+
74
+
75
+ subject.__prv__remove_queue(q4)
76
+ subject.__prv__get_queues.should eq([])
77
+ end
78
+
79
+
80
+ end
81
+
82
+ context "single priority" do
83
+
84
+ subject { BackgroundQueue::ServerLib::PriorityQueue.new }
85
+
86
+ it "adds a single entry" do
87
+ subject.push(SimpleItem.new(2, 1))
88
+ subject.__prv__get_queues.length.should eq(1)
89
+ subject.__prv__get_queues.first.priority.should eq(1)
90
+ subject.__prv__get_queues.first.first.id.should eq(2)
91
+
92
+ end
93
+
94
+ it "returns a single entry" do
95
+ subject.push(SimpleItem.new(2, 1))
96
+ popped = subject.pop
97
+ popped.id.should eq(2)
98
+ subject.__prv__get_queues.length.should eq(0)
99
+ end
100
+
101
+ it "returns nil if empty" do
102
+ subject.pop.should eq(nil)
103
+ end
104
+
105
+ it "returns entries in same order added" do
106
+ subject.push(SimpleItem.new(2, 1))
107
+ subject.push(SimpleItem.new(3, 1))
108
+ subject.pop.id.should eq(2)
109
+ subject.pop.id.should eq(3)
110
+ subject.__prv__get_queues.length.should eq(0)
111
+ end
112
+
113
+ end
114
+
115
+ context "multiple priorities" do
116
+ subject { BackgroundQueue::ServerLib::PriorityQueue.new }
117
+
118
+ it "can add multiple entries" do
119
+ subject.push(SimpleItem.new(2, 2))
120
+ subject.push(SimpleItem.new(3, 1))
121
+ subject.__prv__get_queues.length.should eq(2)
122
+ subject.__prv__get_queues.first.priority.should eq(1)
123
+ subject.__prv__get_queues.last.priority.should eq(2)
124
+ end
125
+
126
+ it "returns entries in correct priority" do
127
+ subject.push(SimpleItem.new(2, 2))
128
+ subject.push(SimpleItem.new(3, 1))
129
+
130
+ subject.pop.id.should eq(3)
131
+ subject.pop.id.should eq(2)
132
+ subject.__prv__get_queues.length.should eq(0)
133
+ end
134
+
135
+ it "returns entries in correct priority and added order" do
136
+ subject.push(SimpleItem.new(2, 2))
137
+ subject.push(SimpleItem.new(3, 3))
138
+ subject.push(SimpleItem.new(4, 2))
139
+
140
+ subject.pop.id.should eq(2)
141
+ subject.pop.id.should eq(4)
142
+ subject.pop.id.should eq(3)
143
+ subject.__prv__get_queues.length.should eq(0)
144
+ end
145
+
146
+ it "knows the highest priority" do
147
+ subject.push(SimpleItem.new(2, 2))
148
+ subject.priority.should eq(2)
149
+ subject.push(SimpleItem.new(3, 3))
150
+ subject.priority.should eq(2)
151
+ subject.pop.id.should eq(2)
152
+ subject.priority.should eq(3)
153
+ subject.pop.id.should eq(3)
154
+ subject.priority.should eq(nil)
155
+ end
156
+
157
+ it "can remove existing item" do
158
+ subject.push(SimpleItem.new(2, 2))
159
+ subject.push(SimpleItem.new(3, 3))
160
+ subject.remove(SimpleItem.new(2, 2))
161
+ subject.__prv__get_queues.length.should eq(1)
162
+ subject.__prv__get_queues.first.priority.should eq(3)
163
+ end
164
+
165
+ end
166
+
167
+ context "#each_item" do
168
+
169
+ subject { BackgroundQueue::ServerLib::PriorityQueue.new }
170
+
171
+ it "will iterate accross the items" do
172
+ subject.push(SimpleItem.new(2, 2))
173
+ subject.push(SimpleItem.new(3, 3))
174
+ subject.push(SimpleItem.new(4, 2))
175
+
176
+ found = []
177
+ subject.each_item { |item| found << item.id }
178
+
179
+ found.should eq([2,4,3])
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,353 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'background_queue_server'
3
+
4
+
5
+ describe BackgroundQueue::ServerLib::Server do
6
+
7
+ context "#process_args" do
8
+ it "knows the start command" do
9
+ options = subject.process_args(["start", "-c", "the_path"])
10
+ options[:command].should eq(:start)
11
+ end
12
+
13
+ it "knows short version of config file path" do
14
+ options = subject.process_args(["start", "-c", "the_path"])
15
+ options[:config].should eq("the_path")
16
+ end
17
+
18
+ it "knows long version of config file path" do
19
+ options = subject.process_args(["start", "--config", "the_path"])
20
+ options[:config].should eq("the_path")
21
+ end
22
+
23
+ it "raises an error if no config file is specified when starting" do
24
+ expect { subject.process_args(["start"]) }.to raise_exception
25
+ end
26
+
27
+
28
+ it "knows the stop command" do
29
+ options = subject.process_args(["stop"])
30
+ options[:command].should eq(:stop)
31
+ end
32
+
33
+ it "knows the test command" do
34
+ options = subject.process_args(["test", "-c", "the_path"])
35
+ options[:command].should eq(:test)
36
+ end
37
+
38
+ it "raises an error if no config file is specified when testing" do
39
+ expect { subject.process_args(["test"]) }.to raise_exception
40
+ end
41
+
42
+ it "raises an error if the command is not recognised" do
43
+ expect { subject.process_args(["blah"]) }.to raise_exception
44
+ end
45
+
46
+ it "knows the short logging path flag" do
47
+ options = subject.process_args(["stop", "-l", "the_path"])
48
+ options[:log_file].should eq("the_path")
49
+ end
50
+
51
+ it "knows the long logging path flag" do
52
+ options = subject.process_args(["stop", "--logfile", "the_path"])
53
+ options[:log_file].should eq("the_path")
54
+ end
55
+
56
+ it "knows the short logging level flag" do
57
+ options = subject.process_args(["stop", "-v", "debug"])
58
+ options[:log_level].should eq("debug")
59
+ end
60
+
61
+ it "knows the long logging level flag" do
62
+ options = subject.process_args(["stop", "--loglevel", "debug"])
63
+ options[:log_level].should eq("debug")
64
+ end
65
+
66
+ it "knows the short pid path flag" do
67
+ options = subject.process_args(["stop", "-p", "the_path"])
68
+ options[:pid_file].should eq("the_path")
69
+ end
70
+
71
+ it "knows the long pid path flag" do
72
+ options = subject.process_args(["stop", "--pidfile", "the_path"])
73
+ options[:pid_file].should eq("the_path")
74
+ end
75
+ end
76
+
77
+ context "#load_configuration" do
78
+ it "will continue if successful" do
79
+ BackgroundQueue::Config.should_receive(:load_file).with(:path).and_return(true)
80
+ subject.load_configuration(:path).should be_true
81
+ end
82
+
83
+ it "will raise an error if configuration does not load" do
84
+ BackgroundQueue::Config.should_receive(:load_file).with(:path).and_raise("nooo!")
85
+ expect { subject.load_configuration(:path) }.to raise_exception("nooo!")
86
+ end
87
+ end
88
+
89
+ context "#resolve_logging_path" do
90
+ it "will handle an absolute path" do
91
+ subject.resolve_logging_path("/path").should eq("/path")
92
+ end
93
+
94
+ it "will use current working directory when given a relative path" do
95
+ Dir.chdir("/tmp")
96
+ subject.resolve_logging_path("path").should eq("/tmp/path")
97
+ end
98
+ end
99
+
100
+ context "#set_logging_level" do
101
+ it "will set level debug" do
102
+ log = Logger.new(STDOUT)
103
+ subject.set_logging_level(log, "debug")
104
+ log.level.should eq(Logger::DEBUG)
105
+ subject.set_logging_level(log, "DEBUG")
106
+ log.level.should eq(Logger::DEBUG)
107
+ end
108
+
109
+ it "will set level info" do
110
+ log = Logger.new(STDOUT)
111
+ subject.set_logging_level(log, "info")
112
+ log.level.should eq(Logger::INFO)
113
+ end
114
+
115
+ it "will set level warning" do
116
+ log = Logger.new(STDOUT)
117
+ subject.set_logging_level(log, "warn")
118
+ log.level.should eq(Logger::WARN)
119
+ end
120
+
121
+ it "will set level error" do
122
+ log = Logger.new(STDOUT)
123
+ subject.set_logging_level(log, "error")
124
+ log.level.should eq(Logger::ERROR)
125
+ end
126
+
127
+ it "will set level fatal" do
128
+ log = Logger.new(STDOUT)
129
+ subject.set_logging_level(log, "fatal")
130
+ log.level.should eq(Logger::FATAL)
131
+ end
132
+
133
+ it "will default to warning" do
134
+ log = Logger.new(STDOUT)
135
+ subject.set_logging_level(log, nil)
136
+ log.level.should eq(Logger::WARN)
137
+ subject.set_logging_level(log, '')
138
+ log.level.should eq(Logger::WARN)
139
+ end
140
+
141
+ it "will error when the level is not recognised" do
142
+ log = Logger.new(STDOUT)
143
+ expect { subject.set_logging_level(log, "argh") }.to raise_exception
144
+ end
145
+ end
146
+
147
+ context "#init_logging" do
148
+ it "will initialize when everything works" do
149
+ Logger.should_receive(:new).with(:resolved_path, 'daily').and_return(:logger)
150
+ subject.should_receive(:resolve_logging_path).with(:path).and_return(:resolved_path)
151
+ subject.should_receive(:set_logging_level).with(:logger, "debug").and_return(nil)
152
+ subject.init_logging(:path, "debug")
153
+ end
154
+
155
+ it "will skip logging if the log path is nil" do
156
+ subject.init_logging(nil, "debug")
157
+ subject.init_logging(' ', "debug")
158
+ end
159
+
160
+
161
+ it "will error when the logfile cannot be opened" do
162
+ subject.should_receive(:resolve_logging_path).with(:path).and_return(:resolved_path)
163
+ Logger.should_receive(:new).with(:resolved_path, 'daily').and_raise("cannot open")
164
+ expect { subject.init_logging(:path, "debug") }.to raise_exception("Error initializing log file resolved_path: cannot open")
165
+ end
166
+ end
167
+
168
+ context "#get_pid_path" do
169
+ it "will use /var/run if pid i not specified on command line" do
170
+ subject.get_pid_path({:pid_file=>:pid}).should eq(:pid)
171
+ end
172
+
173
+ it "will use the command line path if passed" do
174
+ subject.get_pid_path({}).should eq("/var/run/background_queue.pid")
175
+ end
176
+ end
177
+
178
+ context "#get_pid" do
179
+ it "will return the pid if in the pid file and the process is running" do
180
+ f = double("file", :read=>"123")
181
+ File.should_receive(:open).with(:pid_path).and_yield(f)
182
+ Process.should_receive(:kill).with(0, 123).and_return(nil)
183
+ subject.get_pid({:pid_file=>:pid_path}).should eq(123)
184
+ end
185
+
186
+ it "will return nil if the pid file does not exist" do
187
+ File.should_receive(:open).with(:pid_path).and_raise("file not found")
188
+ subject.get_pid({:pid_file=>:pid_path}).should be_nil
189
+ end
190
+
191
+ it "will return nil if the process is not running" do
192
+ f = double("file", :read=>"123")
193
+ File.should_receive(:open).with(:pid_path).and_yield(f)
194
+ Process.should_receive(:kill).with(0, 123).and_raise("not running")
195
+ subject.get_pid({:pid_file=>:pid_path}).should be_nil
196
+ end
197
+
198
+ it "will return nil if the pid is 0" do
199
+ f = double("file", :read=>"")
200
+ File.should_receive(:open).with(:pid_path).and_yield(f)
201
+ subject.get_pid({:pid_file=>:pid_path}).should be_nil
202
+ end
203
+ end
204
+
205
+ context "#check_not_running" do
206
+ it "will return if the pid is nil" do
207
+ subject.should_receive(:get_pid).and_return(nil)
208
+ subject.check_not_running({})
209
+ end
210
+
211
+ it "will raise an error if the pid is not nil" do
212
+ subject.should_receive(:get_pid).and_return(123)
213
+ expect { subject.check_not_running({}) }.to raise_exception("Process 123 already running")
214
+ end
215
+ end
216
+
217
+ context "#kill_pid" do
218
+ it "will do nothing if the pid is nil" do
219
+ subject.should_receive(:get_pid).and_return(nil)
220
+ subject.kill_pid({})
221
+ end
222
+
223
+ it "will kill the pid if it exists" do
224
+ subject.should_receive(:get_pid).and_return(123)
225
+ Process.should_receive(:kill).with(9, 123).and_return(nil)
226
+ subject.kill_pid({})
227
+ end
228
+ end
229
+
230
+ context "#write_pid" do
231
+ before do
232
+ Process.should_receive(:pid).and_return(123)
233
+ end
234
+ it "will write the pid file with the current process id" do
235
+ f = double("file")
236
+ f.should_receive("write").with("123")
237
+ File.should_receive(:open).with(:pid, "w").and_yield(f)
238
+ subject.write_pid({:pid_file=>:pid})
239
+ end
240
+
241
+ it "will error if the pid file cannot be opened" do
242
+ File.should_receive(:open).with(:pid, "w").and_raise("permission denied")
243
+ expect { subject.write_pid({:pid_file=>:pid}) }.to raise_exception("Unable to write to pid file pid: permission denied")
244
+ end
245
+ end
246
+
247
+ context "#remove_pid" do
248
+ it "will remove the file if it exists" do
249
+ File.should_receive(:delete).with(:pid)
250
+ subject.remove_pid({:pid_file=>:pid})
251
+ end
252
+
253
+ it "will do nothing if the pid file does not exist" do
254
+ File.should_receive(:delete).with(:pid).and_raise("aaarrrgggghhh")
255
+ subject.remove_pid({:pid_file=>:pid})
256
+ end
257
+ end
258
+
259
+ context "#load_tasks" do
260
+ it "will do nothing if the task_file is nil" do
261
+ File.should_not_receive(:exist?)
262
+ subject.load_tasks(nil)
263
+ end
264
+
265
+ it "will not load the tasks if the path does not exist" do
266
+ File.should_receive(:exist?).with('path').and_return(false)
267
+ File.should_not_receive(:open)
268
+ subject.load_tasks('path')
269
+ end
270
+
271
+ it "will load the tasks from the path" do
272
+ File.should_receive(:exist?).with('path').and_return(true)
273
+ File.should_receive(:open).with('path', 'r').and_yield(:io)
274
+ task_queue = double("tq")
275
+ task_queue.should_receive(:load_from_file).with(:io)
276
+ subject.stub(:task_queue) { task_queue }
277
+ subject.load_tasks('path')
278
+ end
279
+
280
+ it "will log errors when loading the file" do
281
+ File.should_receive(:exist?).with('path').and_return(true)
282
+ File.should_receive(:open).with('path', 'r').and_yield(:io)
283
+ task_queue = double("tq")
284
+ task_queue.should_receive(:load_from_file).with(:io).and_raise("ERROR")
285
+ subject.stub(:task_queue) { task_queue }
286
+
287
+ logger = double("logger")
288
+ logger.should_receive(:error)
289
+ logger.should_receive(:debug)
290
+ subject.stub(:logger) { logger }
291
+ subject.load_tasks('path')
292
+
293
+ end
294
+
295
+ end
296
+
297
+ context "#save_tasks" do
298
+ it "will do nothing if the task_file is nil" do
299
+ File.should_not_receive(:exist?)
300
+ subject.save_tasks(nil)
301
+ end
302
+
303
+ it "will save the tasks to the path" do
304
+ File.should_receive(:open).with('path', 'w').and_yield(:io)
305
+ task_queue = double("tq")
306
+ task_queue.should_receive(:save_to_file).with(:io)
307
+ subject.stub(:task_queue) { task_queue }
308
+ subject.save_tasks('path')
309
+ end
310
+
311
+ it "will log errors when saving to file" do
312
+ File.should_receive(:open).with('path', 'w').and_yield(:io)
313
+ task_queue = double("tq")
314
+ task_queue.should_receive(:save_to_file).with(:io).and_raise("ERROR")
315
+ subject.stub(:task_queue) { task_queue }
316
+
317
+ logger = double("logger")
318
+ logger.should_receive(:error)
319
+ logger.should_receive(:debug)
320
+ subject.stub(:logger) { logger }
321
+ subject.save_tasks('path')
322
+
323
+ end
324
+
325
+ end
326
+
327
+ context "#start" do
328
+ it "will load configuration, init logging then deamonise" do
329
+ subject.should_receive(:load_configuration).and_return(nil)
330
+ subject.should_receive(:init_logging).and_return(nil)
331
+ subject.should_receive(:check_not_running).and_return(nil)
332
+ subject.should_receive(:write_pid).and_return(nil)
333
+ subject.should_receive(:daemonize).and_return(nil)
334
+ subject.start({:command=>:start})
335
+ end
336
+
337
+ it "will load configuration, init logging then run directly" do
338
+ subject.should_receive(:load_configuration).and_return(nil)
339
+ subject.should_receive(:init_logging).and_return(nil)
340
+ subject.should_receive(:check_not_running).and_return(nil)
341
+ subject.should_receive(:write_pid).and_return(nil)
342
+ subject.should_receive(:run).and_return(nil)
343
+ subject.should_not_receive(:daemonize)
344
+ subject.start({:command=>:run})
345
+ end
346
+
347
+ it "will display any error and exit" do
348
+ subject.should_receive(:load_configuration).and_raise(BackgroundQueue::ServerLib::InitError.new("some_error"))
349
+ STDERR.should_receive(:puts).with("some_error")
350
+ subject.start({:command=>:run})
351
+ end
352
+ end
353
+ end