perfectqueue 0.7.32 → 0.8.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/.gitignore +6 -0
- data/ChangeLog +0 -62
- data/Gemfile +3 -0
- data/README.md +239 -0
- data/Rakefile +19 -0
- data/lib/perfectqueue.rb +68 -4
- data/lib/perfectqueue/application.rb +30 -0
- data/lib/perfectqueue/application/base.rb +27 -0
- data/lib/perfectqueue/application/dispatch.rb +73 -0
- data/lib/perfectqueue/application/router.rb +69 -0
- data/lib/perfectqueue/backend.rb +44 -47
- data/lib/perfectqueue/backend/rdb_compat.rb +298 -0
- data/lib/perfectqueue/blocking_flag.rb +84 -0
- data/lib/perfectqueue/client.rb +117 -0
- data/lib/perfectqueue/command/perfectqueue.rb +108 -323
- data/lib/perfectqueue/daemons_logger.rb +80 -0
- data/lib/perfectqueue/engine.rb +85 -123
- data/lib/perfectqueue/error.rb +53 -0
- data/lib/perfectqueue/model.rb +37 -0
- data/lib/perfectqueue/multiprocess.rb +31 -0
- data/lib/perfectqueue/multiprocess/child_process.rb +108 -0
- data/lib/perfectqueue/multiprocess/child_process_monitor.rb +109 -0
- data/lib/perfectqueue/multiprocess/fork_processor.rb +164 -0
- data/lib/perfectqueue/multiprocess/thread_processor.rb +123 -0
- data/lib/perfectqueue/queue.rb +58 -0
- data/lib/perfectqueue/runner.rb +39 -0
- data/lib/perfectqueue/signal_queue.rb +112 -0
- data/lib/perfectqueue/task.rb +103 -0
- data/lib/perfectqueue/task_metadata.rb +98 -0
- data/lib/perfectqueue/task_monitor.rb +189 -0
- data/lib/perfectqueue/task_status.rb +27 -0
- data/lib/perfectqueue/version.rb +1 -3
- data/lib/perfectqueue/worker.rb +114 -196
- data/perfectqueue.gemspec +24 -0
- data/spec/queue_spec.rb +234 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/worker_spec.rb +81 -0
- metadata +93 -40
- checksums.yaml +0 -7
- data/README.rdoc +0 -224
- data/lib/perfectqueue/backend/null.rb +0 -33
- data/lib/perfectqueue/backend/rdb.rb +0 -181
- data/lib/perfectqueue/backend/simpledb.rb +0 -139
- data/test/backend_test.rb +0 -259
- data/test/cat.sh +0 -2
- data/test/echo.sh +0 -4
- data/test/exec_test.rb +0 -61
- data/test/fail.sh +0 -2
- data/test/huge.sh +0 -2
- data/test/stress.rb +0 -99
- data/test/success.sh +0 -2
- 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 +=
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
84
|
-
|
85
|
-
}
|
16
|
+
]
|
17
|
+
op.version = PerfectQueue::VERSION
|
86
18
|
|
87
|
-
|
88
|
-
|
89
|
-
|
19
|
+
env = ENV['RAILS_ENV'] || 'development'
|
20
|
+
config_path = 'config/perfectqueue.yml'
|
21
|
+
include_dirs = []
|
22
|
+
require_files = []
|
90
23
|
|
91
|
-
|
92
|
-
conf[:poll_interval] = i
|
24
|
+
task_options = {
|
93
25
|
}
|
94
26
|
|
95
|
-
op.
|
96
|
-
conf[:retry_wait] = i
|
97
|
-
}
|
27
|
+
op.separator("options:")
|
98
28
|
|
99
|
-
op.on('-
|
100
|
-
|
29
|
+
op.on('-e', '--environment ENV', 'Framework environment (default: development)') {|s|
|
30
|
+
env = s
|
101
31
|
}
|
102
32
|
|
103
|
-
op.on('-
|
104
|
-
|
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('--
|
110
|
-
|
39
|
+
op.on('-u', '--user USER', 'Set user') {|s|
|
40
|
+
task_options[:user] = s
|
111
41
|
}
|
112
42
|
|
113
|
-
op.on('--
|
114
|
-
|
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.
|
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('-
|
145
|
-
|
50
|
+
op.on('-I', '--include PATH', 'Add $LOAD_PATH directory') {|s|
|
51
|
+
include_dirs << s
|
146
52
|
}
|
147
53
|
|
148
|
-
op.on('-
|
149
|
-
|
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 "
|
61
|
+
puts "\nerror: #{msg}" if msg
|
157
62
|
exit 1
|
158
63
|
end
|
159
64
|
end
|
160
65
|
|
161
|
-
|
162
66
|
begin
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
282
|
-
|
283
|
-
|
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
|
-
|
289
|
-
|
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
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
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
|
-
|
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
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
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
|
|