perfectqueue 0.7.32 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +6 -0
  2. data/ChangeLog +0 -62
  3. data/Gemfile +3 -0
  4. data/README.md +239 -0
  5. data/Rakefile +19 -0
  6. data/lib/perfectqueue.rb +68 -4
  7. data/lib/perfectqueue/application.rb +30 -0
  8. data/lib/perfectqueue/application/base.rb +27 -0
  9. data/lib/perfectqueue/application/dispatch.rb +73 -0
  10. data/lib/perfectqueue/application/router.rb +69 -0
  11. data/lib/perfectqueue/backend.rb +44 -47
  12. data/lib/perfectqueue/backend/rdb_compat.rb +298 -0
  13. data/lib/perfectqueue/blocking_flag.rb +84 -0
  14. data/lib/perfectqueue/client.rb +117 -0
  15. data/lib/perfectqueue/command/perfectqueue.rb +108 -323
  16. data/lib/perfectqueue/daemons_logger.rb +80 -0
  17. data/lib/perfectqueue/engine.rb +85 -123
  18. data/lib/perfectqueue/error.rb +53 -0
  19. data/lib/perfectqueue/model.rb +37 -0
  20. data/lib/perfectqueue/multiprocess.rb +31 -0
  21. data/lib/perfectqueue/multiprocess/child_process.rb +108 -0
  22. data/lib/perfectqueue/multiprocess/child_process_monitor.rb +109 -0
  23. data/lib/perfectqueue/multiprocess/fork_processor.rb +164 -0
  24. data/lib/perfectqueue/multiprocess/thread_processor.rb +123 -0
  25. data/lib/perfectqueue/queue.rb +58 -0
  26. data/lib/perfectqueue/runner.rb +39 -0
  27. data/lib/perfectqueue/signal_queue.rb +112 -0
  28. data/lib/perfectqueue/task.rb +103 -0
  29. data/lib/perfectqueue/task_metadata.rb +98 -0
  30. data/lib/perfectqueue/task_monitor.rb +189 -0
  31. data/lib/perfectqueue/task_status.rb +27 -0
  32. data/lib/perfectqueue/version.rb +1 -3
  33. data/lib/perfectqueue/worker.rb +114 -196
  34. data/perfectqueue.gemspec +24 -0
  35. data/spec/queue_spec.rb +234 -0
  36. data/spec/spec_helper.rb +44 -0
  37. data/spec/worker_spec.rb +81 -0
  38. metadata +93 -40
  39. checksums.yaml +0 -7
  40. data/README.rdoc +0 -224
  41. data/lib/perfectqueue/backend/null.rb +0 -33
  42. data/lib/perfectqueue/backend/rdb.rb +0 -181
  43. data/lib/perfectqueue/backend/simpledb.rb +0 -139
  44. data/test/backend_test.rb +0 -259
  45. data/test/cat.sh +0 -2
  46. data/test/echo.sh +0 -4
  47. data/test/exec_test.rb +0 -61
  48. data/test/fail.sh +0 -2
  49. data/test/huge.sh +0 -2
  50. data/test/stress.rb +0 -99
  51. data/test/success.sh +0 -2
  52. data/test/test_helper.rb +0 -19
@@ -0,0 +1,84 @@
1
+ #
2
+ # PerfectQueue
3
+ #
4
+ # Copyright (C) 2012 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module PerfectQueue
20
+
21
+ class BlockingFlag
22
+ def initialize
23
+ require 'thread'
24
+ @set = false
25
+ @mutex = Mutex.new
26
+ @cond = ConditionVariable.new
27
+ end
28
+
29
+ def set!
30
+ toggled = false
31
+ @mutex.synchronize do
32
+ unless @set
33
+ @set = true
34
+ toggled = true
35
+ end
36
+ @cond.broadcast
37
+ end
38
+ return toggled
39
+ end
40
+
41
+ def reset!
42
+ toggled = false
43
+ @mutex.synchronize do
44
+ if @set
45
+ @set = false
46
+ toggled = true
47
+ end
48
+ @cond.broadcast
49
+ end
50
+ return toggled
51
+ end
52
+
53
+ def set?
54
+ @set
55
+ end
56
+
57
+ def set_region(&block)
58
+ set!
59
+ begin
60
+ block.call
61
+ ensure
62
+ reset!
63
+ end
64
+ end
65
+
66
+ def reset_region(&block)
67
+ reset!
68
+ begin
69
+ block.call
70
+ ensure
71
+ set!
72
+ end
73
+ end
74
+
75
+ def wait(timeout=nil)
76
+ @mutex.synchronize do
77
+ @cond.wait(@mutex, timeout)
78
+ end
79
+ self
80
+ end
81
+ end
82
+
83
+ end
84
+
@@ -0,0 +1,117 @@
1
+ #
2
+ # PerfectQueue
3
+ #
4
+ # Copyright (C) 2012 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module PerfectQueue
20
+ class Client
21
+ def initialize(config)
22
+ @config = {}
23
+ config.each_pair {|k,v| @config[k.to_sym] = v }
24
+
25
+ @backend = Backend.new_backend(self, @config)
26
+
27
+ @max_acquire = @config[:max_acquire] || 1
28
+ @retention_time = @config[:retention_time] || 300
29
+ @alive_time = @config[:alive_time] || 300
30
+ @retry_wait = @config[:retry_wait] || 300 # TODO retry wait algorithm
31
+ end
32
+
33
+ attr_reader :backend
34
+ attr_reader :config
35
+
36
+ def init_database(options={})
37
+ @backend.init_database(options)
38
+ end
39
+
40
+ def get_task_metadata(key, options={})
41
+ @backend.get_task_metadata(key, options)
42
+ end
43
+
44
+ # :message => nil
45
+ # :alive_time => @alive_time
46
+ def preempt(key, options={})
47
+ alive_time = options[:alive_time] || @alive_time
48
+
49
+ @backend.preempt(key, alive_time, options)
50
+ end
51
+
52
+ def list(options={}, &block)
53
+ @backend.list(options, &block)
54
+ end
55
+
56
+ # :run_at => Time.now
57
+ # :message => nil
58
+ # :user => nil
59
+ # :priority => nil
60
+ def submit(key, type, data, options={})
61
+ @backend.submit(key, type, data, options)
62
+ end
63
+
64
+ # :max_acquire => nil
65
+ # :alive_time => nil
66
+ def acquire(options={})
67
+ alive_time = options[:alive_time] || @alive_time
68
+ max_acquire = options[:max_acquire] || @max_acquire
69
+
70
+ @backend.acquire(alive_time, max_acquire, options)
71
+ end
72
+
73
+ # :message => nil
74
+ def cancel_request(key, options={})
75
+ @backend.cancel_request(key, options)
76
+ end
77
+
78
+ def force_finish(key, options={})
79
+ retention_time = options[:retention_time] || @retention_time
80
+
81
+ @backend.force_finish(key, retention_time, options)
82
+ end
83
+
84
+ # :message => nil
85
+ # :retention_time => default_retention_time
86
+ def finish(task_token, options={})
87
+ retention_time = options[:retention_time] || @retention_time
88
+
89
+ @backend.finish(task_token, retention_time, options)
90
+ end
91
+
92
+ # :message => nil
93
+ # :alive_time => nil
94
+ def heartbeat(task_token, options={})
95
+ alive_time = options[:alive_time] || @alive_time
96
+
97
+ @backend.heartbeat(task_token, alive_time, options)
98
+ end
99
+
100
+ def release(task_token, options={})
101
+ alive_time = options[:alive_time] || 0
102
+
103
+ @backend.heartbeat(task_token, alive_time, options)
104
+ end
105
+
106
+ def retry(task_token, options={})
107
+ alive_time = options[:retry_wait] || @retry_wait
108
+
109
+ @backend.heartbeat(task_token, alive_time, options)
110
+ end
111
+
112
+ def close
113
+ @backend.close
114
+ end
115
+ end
116
+ end
117
+
@@ -3,380 +3,165 @@ require 'perfectqueue/version'
3
3
 
4
4
  op = OptionParser.new
5
5
 
6
- op.banner += " [-- <ARGV-for-exec-or-run>]"
7
- op.version = PerfectQueue::VERSION
8
-
9
- type = nil
10
- id = nil
11
- data = nil
12
- confout = nil
13
-
14
- defaults = {
15
- :timeout => 600,
16
- :poll_interval => 1,
17
- :kill_interval => 60,
18
- :workers => 1,
19
- :expire => 345600,
20
- }
21
-
22
- conf = { }
23
-
24
-
25
- op.on('-o', '--log PATH', "log file path") {|s|
26
- conf[:log] = s
27
- }
28
-
29
- op.on('-v', '--verbose', "verbose mode", TrueClass) {|b|
30
- conf[:verbose] = true
31
- }
32
- op.separator("")
33
-
34
- op.on('--push <ID> <DATA>', 'Push a task to the queue') {|s|
35
- type = :push
36
- id = s
37
- }
38
-
39
- op.on('--list', 'Show queued tasks', TrueClass) {|b|
40
- type = :list
41
- }
42
-
43
- op.on('--cancel <ID>', 'Cancel a queued task') {|s|
44
- type = :cancel
45
- id = s
46
- }
6
+ op.banner += %[ <command>
47
7
 
48
- op.on('--configure <PATH.yaml>', 'Write configuration file') {|s|
49
- type = :conf
50
- confout = s
51
- }
52
-
53
- op.separator("")
54
-
55
- op.on('--exec <COMMAND>', 'Execute command') {|s|
56
- type = :exec
57
- conf[:exec] = s
58
- }
59
-
60
- op.on('--run <SCRIPT.rb>', 'Run method named \'run\' defined in the script') {|s|
61
- type = :run
62
- conf[:run] = s
63
- }
64
-
65
- op.separator("")
66
-
67
- op.on('-f', '--file <PATH.yaml>', 'Read configuration file') {|s|
68
- (conf[:files] ||= []) << s
69
- }
70
-
71
- op.on('-C', '--run-class', 'Class name for --run (default: ::Run)') {|s|
72
- conf[:run_class] = s
73
- }
74
-
75
- op.on('-t', '--timeout <SEC>', 'Time for another worker to take over a task when this worker goes down (default: 600)', Integer) {|i|
76
- conf[:timeout] = i
77
- }
78
-
79
- op.on('-b', '--heartbeat-interval <SEC>', 'Threshold time to extend the timeout (heartbeat interval) (default: timeout * 3/4)', Integer) {|i|
80
- conf[:heartbeat_interval] = i
81
- }
8
+ commands:
9
+ list Show list of tasks
10
+ submit <key> <type> <data> Submit a new task
11
+ cancel_request <key> Cancel request
12
+ force_finish <key> Force finish a task
13
+ run <class> Run a worker process
14
+ init Initialize a backend database
82
15
 
83
- op.on('-x', '--kill-timeout <SEC>', 'Threshold time to kill a task process (default: timeout * 10)', Integer) {|i|
84
- conf[:kill_timeout] = i
85
- }
16
+ ]
17
+ op.version = PerfectQueue::VERSION
86
18
 
87
- op.on('-X', '--kill-interval <SEC>', 'Threshold time to retry killing a task process (default: 60)', Integer) {|i|
88
- conf[:kill_interval] = i
89
- }
19
+ env = ENV['RAILS_ENV'] || 'development'
20
+ config_path = 'config/perfectqueue.yml'
21
+ include_dirs = []
22
+ require_files = []
90
23
 
91
- op.on('-i', '--poll-interval <SEC>', 'Polling interval (default: 1)', Integer) {|i|
92
- conf[:poll_interval] = i
24
+ task_options = {
93
25
  }
94
26
 
95
- op.on('-r', '--retry-wait <SEC>', 'Time to retry a task when it is failed (default: same as timeout)', Integer) {|i|
96
- conf[:retry_wait] = i
97
- }
27
+ op.separator("options:")
98
28
 
99
- op.on('-D', '--delete-wait <SEC>', 'Time to delete a finished task when it succeeded (default: 3600)', Integer) {|i|
100
- conf[:delete_wait] = i
29
+ op.on('-e', '--environment ENV', 'Framework environment (default: development)') {|s|
30
+ env = s
101
31
  }
102
32
 
103
- op.on('-e', '--expire <SEC>', 'Threshold time to expire a task (default: 345601 (4days))', Integer) {|i|
104
- conf[:expire] = i
33
+ op.on('-c', '--config PATH.yml', 'Path to a configuration file (default: config/perfectqueue.yml)') {|s|
34
+ config_path = s
105
35
  }
106
36
 
107
- op.separator("")
37
+ op.separator("\noptions for submit:")
108
38
 
109
- op.on('--database <URI>', 'Use RDBMS for the backend database (e.g.: mysql://user:password@localhost/mydb)') {|s|
110
- conf[:backend_database] = s
39
+ op.on('-u', '--user USER', 'Set user') {|s|
40
+ task_options[:user] = s
111
41
  }
112
42
 
113
- op.on('--table <NAME>', 'backend: name of the table (default: perfectqueue)') {|s|
114
- conf[:backend_table] = s
43
+ op.on('-t', '--time UNIXTIME', 'Set time to run the task', Integer) {|i|
44
+ task_options[:run_at] = i
115
45
  }
116
46
 
117
- op.on('--simpledb <DOMAIN>', 'Use Amazon SimpleDB for the backend database (e.g.: --simpledb mydomain -k KEY_ID -s SEC_KEY)') {|s|
118
- conf[:backend_simpledb] = s
119
- }
120
-
121
- op.on('-k', '--key-id <ID>', 'AWS Access Key ID') {|s|
122
- conf[:backend_key_id] = s
123
- }
124
47
 
125
- op.on('-s', '--secret-key <KEY>', 'AWS Secret Access Key') {|s|
126
- conf[:backend_secret_key] = s
127
- }
128
-
129
- op.separator("")
130
-
131
- op.on('-w', '--worker <NUM>', 'Number of worker threads (default: 1)', Integer) {|i|
132
- conf[:workers] = i
133
- }
134
-
135
- op.on('-d', '--daemon <PIDFILE>', 'Daemonize (default: foreground)') {|s|
136
- conf[:daemon] = s
137
- }
138
-
139
- op.on('--env K=V', 'Set environment variable') {|s|
140
- k, v = s.split('=',2)
141
- (conf[:env] ||= {})[k] = v
142
- }
48
+ op.separator("\noptions for run:")
143
49
 
144
- op.on('-o', '--log <PATH>', "log file path") {|s|
145
- conf[:log] = s
50
+ op.on('-I', '--include PATH', 'Add $LOAD_PATH directory') {|s|
51
+ include_dirs << s
146
52
  }
147
53
 
148
- op.on('-v', '--verbose', "verbose mode", TrueClass) {|b|
149
- conf[:verbose] = true
54
+ op.on('-r', '--require PATH', 'Require files before starting') {|s|
55
+ require_files << s
150
56
  }
151
57
 
152
-
153
58
  (class<<self;self;end).module_eval do
154
59
  define_method(:usage) do |msg|
155
60
  puts op.to_s
156
- puts "error: #{msg}" if msg
61
+ puts "\nerror: #{msg}" if msg
157
62
  exit 1
158
63
  end
159
64
  end
160
65
 
161
-
162
66
  begin
163
- if eqeq = ARGV.index('--')
164
- argv = ARGV.slice!(0, eqeq)
165
- ARGV.slice!(0)
166
- else
167
- argv = ARGV.slice!(0..-1)
168
- end
169
- op.parse!(argv)
170
-
171
- case type
172
- when :push
173
- if argv.length != 1
174
- usage nil
175
- end
176
- data = argv[0]
177
-
178
- else
179
- if argv.length != 0
180
- usage nil
181
- end
182
- end
183
-
184
- if conf[:files]
185
- require 'yaml'
186
- docs = ''
187
- conf[:files].each {|file|
188
- docs << File.read(file)
189
- }
190
- y = {}
191
- YAML.load_documents(docs) {|yaml|
192
- yaml.each_pair {|k,v| y[k.to_sym] = v }
193
- }
67
+ op.parse!(ARGV)
68
+
69
+ usage nil if ARGV.empty?
70
+
71
+ cmd = ARGV.shift
72
+ case cmd
73
+ when 'list'
74
+ cmd = :list
75
+ usage nil unless ARGV.length == 0
76
+
77
+ when 'cancel_request' ,'cancel'
78
+ cmd = :cancel
79
+ usage nil unless ARGV.length == 1
80
+ key = ARGV[0]
81
+
82
+ when 'force_finish' ,'finish'
83
+ cmd = :finish
84
+ usage nil unless ARGV.length == 1
85
+ key = ARGV[0]
86
+
87
+ when 'submit'
88
+ cmd = :submit
89
+ usage nil unless ARGV.length == 3
90
+ key, type, data = *ARGV
91
+ require 'json'
92
+ data = JSON.load(data)
93
+
94
+ when 'run'
95
+ cmd = :run
96
+ usage nil unless ARGV.length == 1
97
+ klass = ARGV[0]
98
+
99
+ when 'init'
100
+ cmd = :init
101
+ usage nil unless ARGV.length == 0
194
102
 
195
- conf = defaults.merge(y).merge(conf)
196
-
197
- if ARGV.empty? && conf[:args]
198
- ARGV.clear
199
- ARGV.concat conf[:args]
200
- end
201
103
  else
202
- conf = defaults.merge(conf)
203
- end
204
-
205
- unless type
206
- if conf[:run]
207
- type = :run
208
- elsif conf[:exec]
209
- type = :exec
210
- else
211
- raise "--list, --push, --cancel, --configure, --exec or --run is required"
212
- end
213
- end
214
-
215
- unless conf[:heartbeat_interval]
216
- conf[:heartbeat_interval] = conf[:timeout] * 3/4
217
- end
218
-
219
- unless conf[:kill_timeout]
220
- conf[:kill_timeout] = conf[:timeout] * 10
221
- end
222
-
223
- unless conf[:retry_wait]
224
- conf[:retry_wait] = conf[:timeout]
225
- end
226
-
227
- if conf[:timeout] < conf[:heartbeat_interval]
228
- raise "--heartbeat-interval(=#{conf[:heartbeat_interval]}) must be larger than --timeout(=#{conf[:timeout]})"
229
- end
230
-
231
- if conf[:backend_database]
232
- conf[:backend_table] ||= 'perfectqueue'
233
- backend_proc = Proc.new {
234
- PerfectQueue::RDBBackend.new(conf[:backend_database], conf[:backend_table])
235
- }
236
- elsif conf[:backend_simpledb]
237
- conf[:backend_key_id] ||= ENV['AWS_ACCESS_KEY_ID']
238
- conf[:backend_secret_key] ||= ENV['AWS_SECRET_ACCESS_KEY']
239
- backend_proc = Proc.new {
240
- PerfectQueue::SimpleDBBackend.new(conf[:backend_key_id], conf[:backend_secret_key], conf[:backend_simpledb])
241
- }
242
-
243
- else
244
- raise "--database or --simpledb is required"
104
+ raise "unknown command: '#{cmd}'"
245
105
  end
246
106
 
247
107
  rescue
248
108
  usage $!.to_s
249
109
  end
250
110
 
251
-
252
- if confout
253
- require 'yaml'
254
-
255
- conf.delete(:files)
256
- conf[:args] = ARGV
257
-
258
- y = {}
259
- conf.each_pair {|k,v| y[k.to_s] = v }
260
-
261
- File.open(confout, "w") {|f|
262
- f.write y.to_yaml
263
- }
264
- exit 0
265
- end
266
-
267
-
268
- require 'logger'
111
+ require 'yaml'
269
112
  require 'perfectqueue'
270
- require 'perfectqueue/backend/rdb'
271
- require 'perfectqueue/backend/simpledb'
272
113
 
273
- backend = backend_proc.call
114
+ config_load_proc = Proc.new {
115
+ yaml = YAML.load(File.read(config_path))
116
+ conf = yaml[env]
117
+ unless conf
118
+ raise "Configuration file #{config_path} doesn't include configuration for environment '#{env}'"
119
+ end
120
+ conf
121
+ }
274
122
 
275
- case type
123
+
124
+ case cmd
276
125
  when :list
277
- format = "%26s %26s %26s %26s %s"
278
- puts format % ["id", "created_at", "timeout", "resource", "data"]
279
- time_format = "%Y-%m-%d %H:%M:%S %z"
280
126
  n = 0
281
- backend.list {|id,created_at,data,timeout,resource|
282
- puts format % [id, Time.at(created_at).strftime(time_format), Time.at(timeout).strftime(time_format), resource, data]
283
- n += 1
127
+ PerfectQueue.open(config_load_proc.call) {|queue|
128
+ format = "%30s %15s %18s %18s %28s %28s %s"
129
+ puts format % ["key", "type", "user", "status", "created_at", "timeout", "data"]
130
+ queue.each {|task|
131
+ puts format % [task.key, task.type, task.user, task.status, task.created_at, task.timeout, task.data]
132
+ n += 1
133
+ }
284
134
  }
285
135
  puts "#{n} entries."
286
136
 
287
137
  when :cancel
288
- canceled = backend.cancel(id)
289
- if canceled
290
- puts "Task id=#{id} is canceled."
291
- else
292
- puts "Task id=#{id} does not exist. abort"
293
- end
294
-
295
- when :push
296
- submitted = backend.submit(id, data, Time.now.to_i)
297
- if submitted
298
- puts "Task id=#{id} is submitted."
299
- else
300
- puts "Task id=#{id} is duplicated. abort."
301
- end
302
-
303
- when :exec, :run
304
- if conf[:daemon]
305
- exit!(0) if fork
306
- Process.setsid
307
- exit!(0) if fork
308
- File.umask(0)
309
- STDIN.reopen("/dev/null")
310
- STDOUT.reopen("/dev/null", "w")
311
- STDERR.reopen("/dev/null", "w")
312
- File.open(conf[:daemon], "w") {|f|
313
- f.write Process.pid.to_s
314
- }
315
- end
316
-
317
- (conf[:env] || {}).each_pair {|k,v|
318
- ENV[k] = v
138
+ PerfectQueue.open(config_load_proc.call) {|queue|
139
+ queue[key].cancel_request!
319
140
  }
320
141
 
321
- if type == :run
322
- load File.expand_path(conf[:run])
323
- run_class = eval(conf[:run_class] || 'Run')
324
- else
325
- require 'shellwords'
326
- cmd = conf[:exec]
327
- Run = Class.new(PerfectQueue::ExecRunner) do
328
- define_method(:initialize) {|task|
329
- super(cmd, task)
330
- }
331
- end
332
- run_class = Run
333
- end
334
-
335
- conf[:run_class] = run_class
336
-
337
- if log_file = conf[:log]
338
- log_out = File.open(conf[:log], "a")
339
- else
340
- log_out = STDOUT
341
- end
342
- log_out.sync = true
343
-
344
- log = Logger.new(log_out)
345
- if conf[:verbose]
346
- log.level = Logger::DEBUG
347
- else
348
- log.level = Logger::INFO
349
- end
350
-
351
- engine = PerfectQueue::Engine.new(backend, log, conf)
352
-
353
- trap :INT do
354
- log.info "shutting down..."
355
- engine.stop
356
- end
357
-
358
- trap :TERM do
359
- log.info "shutting down..."
360
- engine.stop
361
- end
142
+ when :finish
143
+ PerfectQueue.open(config_load_proc.call) {|queue|
144
+ queue[key].force_finish!
145
+ }
362
146
 
363
- trap :HUP do
364
- if log_file
365
- log_out.reopen(log_file, "a")
366
- end
367
- end
147
+ when :submit
148
+ PerfectQueue.open(config_load_proc.call) {|queue|
149
+ queue.submit(key, type, data, task_options)
150
+ }
368
151
 
369
- log.info "PerfectQueue-#{PerfectQueue::VERSION}"
152
+ when :run
153
+ include_dirs.each {|path|
154
+ $LOAD_PATH << File.expand_path(path)
155
+ }
156
+ require_files.each {|file|
157
+ require file
158
+ }
159
+ klass = Object.const_get(klass)
160
+ PerfectQueue::Worker.run(klass, &config_load_proc)
370
161
 
371
- begin
372
- engine.run
373
- engine.shutdown
374
- rescue
375
- log.error $!.to_s
376
- $!.backtrace.each {|x|
377
- log.error " #{x}"
378
- }
379
- exit 1
380
- end
162
+ when :init
163
+ PerfectQueue.open(config_load_proc.call) {|queue|
164
+ queue.client.init_database
165
+ }
381
166
  end
382
167