background_queue 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,339 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'ipaddress'
|
3
|
+
|
4
|
+
module BackgroundQueue::ServerLib
|
5
|
+
|
6
|
+
#The server configuration which is stored as a YAML file containing a root key for each environments configuration, much like database.yml.
|
7
|
+
#
|
8
|
+
#Example
|
9
|
+
#=======
|
10
|
+
#
|
11
|
+
# development:
|
12
|
+
# address:
|
13
|
+
# host: 127.0.0.1
|
14
|
+
# port: 3000
|
15
|
+
# workers:
|
16
|
+
# - http://127.0.0.1:801/background_queue
|
17
|
+
# secret: this_is_used_to_make_sure_it_is_secure
|
18
|
+
# task_file: /path/to/file/to/save/running/tasks
|
19
|
+
# production:
|
20
|
+
# address:
|
21
|
+
# host: 0.0.0.0
|
22
|
+
# port: 3000
|
23
|
+
# connections_per_worker: 10
|
24
|
+
# workers:
|
25
|
+
# - http://192.168.3.1:801/background_queue
|
26
|
+
# - http://192.168.3.2:801/background_queue
|
27
|
+
# secret: this_is_used_to_make_sure_it_is_secure
|
28
|
+
# system_task_options:
|
29
|
+
# domain: the_default_domain
|
30
|
+
# jobs
|
31
|
+
# - cron: "0 22 * * 1-5"
|
32
|
+
# worker: some_worker
|
33
|
+
# args:
|
34
|
+
# arg1: 22
|
35
|
+
# arg2: "hello"
|
36
|
+
class Config < BackgroundQueue::Config
|
37
|
+
|
38
|
+
#the list of workers that are called using http
|
39
|
+
attr_reader :workers
|
40
|
+
|
41
|
+
|
42
|
+
#the shared secret to make sure the worker is not called directly from the internet
|
43
|
+
attr_reader :secret
|
44
|
+
|
45
|
+
#a path where tasks are saved when the server shuts down, and loaded when it starts back up. This will store tasks being lost when restarting the server.
|
46
|
+
attr_reader :task_file
|
47
|
+
|
48
|
+
#an array of scheduled jobs
|
49
|
+
attr_reader :jobs
|
50
|
+
|
51
|
+
#the address to listen on
|
52
|
+
attr_reader :address
|
53
|
+
|
54
|
+
#the number of connections allowed for each active worker
|
55
|
+
attr_reader :connections_per_worker
|
56
|
+
|
57
|
+
#used for polling task and jobs. Should include a domain entry if your worker uses domain lookups
|
58
|
+
attr_reader :system_task_options
|
59
|
+
|
60
|
+
#load the configration using a hash just containing the environment
|
61
|
+
def self.load_hash(env_config, path)
|
62
|
+
BackgroundQueue::ServerLib::Config.new(
|
63
|
+
build_worker_entries(env_config, path),
|
64
|
+
get_secret_entry(env_config, path),
|
65
|
+
get_address_entry(env_config, path),
|
66
|
+
get_connections_per_worker_entry(env_config, path),
|
67
|
+
get_jobs_entry(env_config, path),
|
68
|
+
get_system_task_options_entry(env_config, path),
|
69
|
+
get_task_file_entry(env_config, path)
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
class << self
|
74
|
+
private
|
75
|
+
|
76
|
+
def build_worker_entries(env_config, path)
|
77
|
+
entries = []
|
78
|
+
workers_entry = BackgroundQueue::Utils.get_hash_entry(env_config, :workers)
|
79
|
+
if workers_entry && workers_entry.kind_of?(Array)
|
80
|
+
workers_entry.each_with_index do |entry, index|
|
81
|
+
begin
|
82
|
+
entries << BackgroundQueue::ServerLib::Config::Worker.new(entry)
|
83
|
+
rescue Exception=>e
|
84
|
+
raise BackgroundQueue::LoadError, "Error loading 'worker' entry (#{index + 1}) from background queue server configuration file #{full_path(path)}: #{e.message}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
elsif workers_entry
|
88
|
+
raise BackgroundQueue::LoadError, "Error loading 'workers' entries configuration file #{full_path(path)}: invalid data type (#{workers_entry.class.name}), expecting Array"
|
89
|
+
else
|
90
|
+
raise BackgroundQueue::LoadError, "Missing 'workers' in background queue server configuration file #{full_path(path)}"
|
91
|
+
end
|
92
|
+
entries
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_secret_entry(env_config, path)
|
96
|
+
secret_entry = BackgroundQueue::Utils.get_hash_entry(env_config, :secret)
|
97
|
+
if secret_entry && secret_entry.kind_of?(String)
|
98
|
+
secret_entry.strip!
|
99
|
+
if secret_entry.length < 20
|
100
|
+
raise BackgroundQueue::LoadError, "Error loading 'secret' entry in background queue server configuration file #{full_path(path)}: length too short (must be at least 20 characters long)"
|
101
|
+
end
|
102
|
+
secret_entry
|
103
|
+
elsif secret_entry
|
104
|
+
raise BackgroundQueue::LoadError, "Error loading 'secret' entry in background queue server configuration file #{full_path(path)}: invalid data type (#{secret_entry.class.name}), expecting String"
|
105
|
+
else
|
106
|
+
raise BackgroundQueue::LoadError, "Missing 'secret' entry in background queue server configuration file #{full_path(path)}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_address_entry(env_config, path)
|
111
|
+
begin
|
112
|
+
BackgroundQueue::ServerLib::Config::Address.new(BackgroundQueue::Utils.get_hash_entry(env_config, :address))
|
113
|
+
rescue Exception=>e
|
114
|
+
raise BackgroundQueue::LoadError, "Error loading 'address' entry in background queue server configuration file #{full_path(path)}: #{e.message}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_connections_per_worker_entry(env_config, path)
|
119
|
+
connections_per_worker_entry = BackgroundQueue::Utils.get_hash_entry(env_config, :connections_per_worker)
|
120
|
+
if connections_per_worker_entry && connections_per_worker_entry.kind_of?(Integer)
|
121
|
+
connections_per_worker_entry
|
122
|
+
elsif connections_per_worker_entry
|
123
|
+
raise BackgroundQueue::LoadError, "Error loading 'connections_per_worker' entry in background queue server configuration file #{full_path(path)}: invalid data type (#{connections_per_worker_entry.class.name}), expecting Integer"
|
124
|
+
else
|
125
|
+
raise BackgroundQueue::LoadError, "Missing 'connections_per_worker' entry in background queue server configuration file #{full_path(path)}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_system_task_options_entry(env_config, path)
|
130
|
+
opts_entry = BackgroundQueue::Utils.get_hash_entry(env_config, :system_task_options)
|
131
|
+
return {} if opts_entry.nil?
|
132
|
+
if opts_entry.kind_of?(Hash)
|
133
|
+
opts_entry
|
134
|
+
else
|
135
|
+
raise BackgroundQueue::LoadError, "Error loading 'system_task_options' entry in background queue server configuration file #{full_path(path)}: invalid data type (#{opts_entry.class.name}), expecting Hash (of options)"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_jobs_entry(env_config, path)
|
140
|
+
jobs_entry = BackgroundQueue::Utils.get_hash_entry(env_config, :jobs)
|
141
|
+
return [] if jobs_entry.nil?
|
142
|
+
if jobs_entry.kind_of?(Array)
|
143
|
+
retval = []
|
144
|
+
for job in jobs_entry
|
145
|
+
begin
|
146
|
+
retval << BackgroundQueue::ServerLib::Config::Job.new(job)
|
147
|
+
rescue Exception=>e
|
148
|
+
raise BackgroundQueue::LoadError, "Error loading 'jobs' entry in background queue server configuration file #{full_path(path)}: #{e.message}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
retval
|
152
|
+
else
|
153
|
+
raise BackgroundQueue::LoadError, "Error loading 'jobs' entry in background queue server configuration file #{full_path(path)}: invalid data type (#{jobs_entry.class.name}), expecting Array (of jobs)"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_task_file_entry(env_config, path)
|
158
|
+
task_file = BackgroundQueue::Utils.get_hash_entry(env_config, :task_file)
|
159
|
+
if task_file && task_file.kind_of?(String)
|
160
|
+
task_file.strip!
|
161
|
+
#make sure the file exists of the directory is writable
|
162
|
+
if !File.exist?(task_file)
|
163
|
+
dir = File.dirname(task_file)
|
164
|
+
if !File.exist?(dir)
|
165
|
+
#check if we can create the directory
|
166
|
+
begin
|
167
|
+
FileUtils.mkdir_p dir
|
168
|
+
rescue Exception=>e
|
169
|
+
raise BackgroundQueue::LoadError, "Error loading 'task_file' entry in background queue server configuration file #{full_path(path)}: unable to create directory #{dir} (#{e.message})"
|
170
|
+
end
|
171
|
+
else
|
172
|
+
#check if we can write in the directory
|
173
|
+
begin
|
174
|
+
FileUtils.touch task_file
|
175
|
+
rescue Exception=>e
|
176
|
+
raise BackgroundQueue::LoadError, "Error loading 'task_file' entry in background queue server configuration file #{full_path(path)}: unable to write to file #{task_file} (#{e.message})"
|
177
|
+
end
|
178
|
+
FileUtils.rm task_file
|
179
|
+
end
|
180
|
+
end
|
181
|
+
task_file
|
182
|
+
elsif task_file
|
183
|
+
raise BackgroundQueue::LoadError, "Error loading 'task_file' entry in background queue server configuration file #{full_path(path)}: Invalid data type (#{task_file.class.name}), expecting String"
|
184
|
+
else
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
#do not call this directly, use a load_* method
|
192
|
+
def initialize(workers, secret, address, connections_per_worker, jobs, system_task_options, task_file)
|
193
|
+
@workers = workers
|
194
|
+
@secret = secret
|
195
|
+
@address = address
|
196
|
+
@connections_per_worker = connections_per_worker
|
197
|
+
@jobs = jobs
|
198
|
+
@system_task_options = system_task_options
|
199
|
+
@task_file = task_file
|
200
|
+
end
|
201
|
+
|
202
|
+
class Address
|
203
|
+
attr_reader :host
|
204
|
+
attr_reader :port
|
205
|
+
|
206
|
+
|
207
|
+
def initialize(config_entry)
|
208
|
+
if config_entry.nil?
|
209
|
+
@host = "0.0.0.0"
|
210
|
+
@port = BackgroundQueue::Config::DEFAULT_PORT
|
211
|
+
else
|
212
|
+
port = BackgroundQueue::Utils.get_hash_entry(config_entry, :port)
|
213
|
+
if port.nil?
|
214
|
+
@port = BackgroundQueue::Config::DEFAULT_PORT
|
215
|
+
elsif port.kind_of?(Numeric)
|
216
|
+
@port = port.to_i
|
217
|
+
elsif port.kind_of?(String)
|
218
|
+
if port.to_s.strip == port.to_s.to_i.to_s
|
219
|
+
@port = port.to_i
|
220
|
+
else
|
221
|
+
raise "Invalid port: #{port}"
|
222
|
+
end
|
223
|
+
else
|
224
|
+
raise "Invalid port: should be number or string"
|
225
|
+
end
|
226
|
+
if @port <= 0
|
227
|
+
raise "Invalid port: must be greater then zero"
|
228
|
+
end
|
229
|
+
host = BackgroundQueue::Utils.get_hash_entry(config_entry, :host)
|
230
|
+
if host.nil?
|
231
|
+
@host = "0.0.0.0"
|
232
|
+
elsif host.kind_of?(String)
|
233
|
+
if IPAddress.valid? host
|
234
|
+
@host = host
|
235
|
+
else
|
236
|
+
raise "Invalid host: #{host}"
|
237
|
+
end
|
238
|
+
else
|
239
|
+
raise "Invalid host: should be string"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
#A server entry in the configuration
|
247
|
+
class Worker
|
248
|
+
|
249
|
+
attr_reader :uri
|
250
|
+
|
251
|
+
def initialize(config_entry)
|
252
|
+
if config_entry.nil?
|
253
|
+
raise BackgroundQueue::LoadError, "Missing worker url"
|
254
|
+
elsif config_entry.kind_of?(String)
|
255
|
+
raise BackgroundQueue::LoadError, "Missing worker url" if config_entry.strip.length == 0
|
256
|
+
begin
|
257
|
+
@uri = URI.parse(config_entry)
|
258
|
+
rescue URI::InvalidURIError
|
259
|
+
raise BackgroundQueue::LoadError, "Invalid worker url (#{config_entry})"
|
260
|
+
end
|
261
|
+
else
|
262
|
+
raise BackgroundQueue::LoadError, "Invalid data type (#{config_entry.class.name}), expecting String (as a url)"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def url
|
267
|
+
@uri.to_s
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class Job
|
272
|
+
|
273
|
+
|
274
|
+
attr_accessor :at
|
275
|
+
attr_accessor :in
|
276
|
+
attr_accessor :cron
|
277
|
+
attr_accessor :every
|
278
|
+
attr_accessor :type
|
279
|
+
attr_accessor :args
|
280
|
+
|
281
|
+
def initialize(job_entry)
|
282
|
+
raise "Empty Job Entry" if job_entry.nil?
|
283
|
+
@at = BackgroundQueue::Utils.get_hash_entry(job_entry, :at)
|
284
|
+
@in = BackgroundQueue::Utils.get_hash_entry(job_entry, :in)
|
285
|
+
@cron = BackgroundQueue::Utils.get_hash_entry(job_entry, :cron)
|
286
|
+
@every = BackgroundQueue::Utils.get_hash_entry(job_entry, :every)
|
287
|
+
if !@at.nil?
|
288
|
+
@type = :at
|
289
|
+
elsif !@in.nil?
|
290
|
+
@type = :in
|
291
|
+
elsif !@cron.nil?
|
292
|
+
@type=:cron
|
293
|
+
elsif !@every.nil?
|
294
|
+
@type=:every
|
295
|
+
else
|
296
|
+
raise "Job is missing timer designation (at, in or cron)"
|
297
|
+
end
|
298
|
+
@worker = BackgroundQueue::Utils.get_hash_entry(job_entry, :worker)
|
299
|
+
raise "Job is missing worker entry" if @worker.nil?
|
300
|
+
|
301
|
+
@args = {}
|
302
|
+
args_entry = BackgroundQueue::Utils.get_hash_entry(job_entry, :args)
|
303
|
+
unless args_entry.nil?
|
304
|
+
raise "Invalid 'args' entry in job: expecting Hash of arguments, got #{args_entry.class.name}" unless args_entry.kind_of?(Hash)
|
305
|
+
@args = args_entry
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
def schedule(scheduler, server)
|
311
|
+
case @type
|
312
|
+
when :at
|
313
|
+
scheduler.at @at do
|
314
|
+
run(server)
|
315
|
+
end
|
316
|
+
when :in
|
317
|
+
scheduler.in @in do
|
318
|
+
run(server)
|
319
|
+
end
|
320
|
+
when :cron
|
321
|
+
scheduler.cron @cron do
|
322
|
+
run(server)
|
323
|
+
end
|
324
|
+
when :every
|
325
|
+
scheduler.every @every do
|
326
|
+
run(server)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
def run(server)
|
332
|
+
task = BackgroundQueue::ServerLib::Task.new(:system, :scheduled, self.object_id, 2, @worker, @args, server.config.system_task_options)
|
333
|
+
server.task_queue.add_task(task)
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
module BackgroundQueue::ServerLib
|
4
|
+
class EventConnection < EventMachine::Connection
|
5
|
+
|
6
|
+
attr_accessor :server
|
7
|
+
|
8
|
+
STAGE_LENGTH = 0
|
9
|
+
STAGE_BODY = 1
|
10
|
+
|
11
|
+
MAX_BODY_LENGTH = 9999999
|
12
|
+
|
13
|
+
|
14
|
+
def post_init
|
15
|
+
@data = ""
|
16
|
+
@length = 0
|
17
|
+
@stage = STAGE_LENGTH
|
18
|
+
end
|
19
|
+
|
20
|
+
def receive_data(data)
|
21
|
+
@data << data
|
22
|
+
if @stage == STAGE_LENGTH
|
23
|
+
if @data.length >= 6
|
24
|
+
s_header = @data.slice!(0,6)
|
25
|
+
version, length = s_header.unpack("SL")
|
26
|
+
|
27
|
+
if version == 1
|
28
|
+
@length = length
|
29
|
+
@stage = STAGE_BODY
|
30
|
+
if length > MAX_BODY_LENGTH || length <= 0
|
31
|
+
raise "Invalid length: #{length}"
|
32
|
+
end
|
33
|
+
else
|
34
|
+
raise "Invalid header version: #{version}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if @stage == STAGE_BODY && @data.length == @length
|
40
|
+
#body received
|
41
|
+
process_data(@data)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_data(data)
|
46
|
+
begin
|
47
|
+
cmd = BackgroundQueue::Command.from_buf(data)
|
48
|
+
result = process_command(cmd)
|
49
|
+
send_result(result)
|
50
|
+
rescue Exception=>e
|
51
|
+
@server.logger.error("Error processing command: #{e.message}")
|
52
|
+
send_error(e.message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_result(command)
|
57
|
+
send(command.to_buf)
|
58
|
+
end
|
59
|
+
|
60
|
+
def send_error(message)
|
61
|
+
send_result(build_simple_command(:error, message))
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_simple_command(type, message)
|
65
|
+
BackgroundQueue::Command.new(type, {}, {:message=>message})
|
66
|
+
end
|
67
|
+
|
68
|
+
def send(data)
|
69
|
+
data_with_header = [1, data.length, data].pack("SLZ#{data.length}")
|
70
|
+
send_data(data_with_header)
|
71
|
+
end
|
72
|
+
|
73
|
+
def process_command(command)
|
74
|
+
case command.code.to_s
|
75
|
+
when 'add_task'
|
76
|
+
process_add_task_command(command)
|
77
|
+
when 'add_tasks'
|
78
|
+
process_add_tasks_command(command)
|
79
|
+
when 'remove_tasks'
|
80
|
+
process_remove_tasks_command(command)
|
81
|
+
when 'get_status'
|
82
|
+
process_get_status_command(command)
|
83
|
+
when 'stats'
|
84
|
+
process_stats_command(command)
|
85
|
+
else
|
86
|
+
raise "Unknown command: #{command.code.inspect}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def process_add_task_command(command)
|
91
|
+
@server.logger.debug("add_task: #{command.args[:owner_id]}, #{command.args[:job_id]}, #{command.args[:task_id]}")
|
92
|
+
task = BackgroundQueue::ServerLib::Task.new(command.args[:owner_id], command.args[:job_id], command.args[:task_id], command.args[:priority], command.args[:worker], command.args[:params], command.options)
|
93
|
+
server.task_queue.add_task(task)
|
94
|
+
@server.change_stat(:tasks, 1)
|
95
|
+
build_simple_command(:result, "ok")
|
96
|
+
end
|
97
|
+
|
98
|
+
def process_add_tasks_command(command)
|
99
|
+
@server.logger.debug("add_tasks: #{command.args[:owner_id]}, #{command.args[:job_id]}, #{command.args[:tasks].inspect}")
|
100
|
+
shared_params = command.args[:shared_parameters]
|
101
|
+
shared_params = {} if shared_params.nil?
|
102
|
+
owner_id = command.args[:owner_id]
|
103
|
+
job_id = command.args[:job_id]
|
104
|
+
priority = command.args[:priority]
|
105
|
+
worker = command.args[:worker]
|
106
|
+
for task_data in command.args[:tasks]
|
107
|
+
if task_data[1].nil?
|
108
|
+
merged_params = shared_params
|
109
|
+
else
|
110
|
+
merged_params = shared_params.clone.update(task_data[1])
|
111
|
+
end
|
112
|
+
task = BackgroundQueue::ServerLib::Task.new(owner_id, job_id, task_data[0], priority, worker, merged_params, command.options)
|
113
|
+
server.task_queue.add_task(task)
|
114
|
+
end
|
115
|
+
@server.change_stat(:tasks, command.args[:tasks].length)
|
116
|
+
build_simple_command(:result, "ok")
|
117
|
+
end
|
118
|
+
|
119
|
+
def process_get_status_command(command)
|
120
|
+
job = @server.jobs.get_job(command.args[:job_id])
|
121
|
+
if job.nil?
|
122
|
+
build_simple_command(:job_not_found, "job #{command.args[:job_id]} not found")
|
123
|
+
else
|
124
|
+
BackgroundQueue::Command.new(:status, {}, job.get_current_progress)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def process_stats_command(command)
|
129
|
+
BackgroundQueue::Command.new(:stats, {}, @server.get_stats)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|