tq 0.1.6 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tq/app.rb +5 -1
- data/lib/tq/queue.rb +24 -3
- data/lib/version.rb +1 -1
- data/test/helper.rb +18 -3
- data/test/test_run.rb +122 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 877e9730d05610f3b211c7a0d69817f60149bde4
|
4
|
+
data.tar.gz: eb2d73a1f7e5a63659fe53041171bde055e59523
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c2539a74728b068c962eab6e1637559664e1a5a74514623893b756166c1246641c5b33dc5892e671ada06a7e2760bba2453137b0ba98f74813c729bbdbaed3b
|
7
|
+
data.tar.gz: 2981fa8c831cf086873d2d9dfd2fef886533dc01baaa5521b0d4ea2f6f6a701ed37a165299f558a92ba3397d98ddab54415f1658bad433192335a261063b9b45
|
data/lib/tq/app.rb
CHANGED
@@ -155,7 +155,11 @@ module TQ
|
|
155
155
|
def _run(qin, qout, qerr)
|
156
156
|
tasks = qin.lease!
|
157
157
|
Parallel.each(tasks, :in_threads => @options['concurrency']) do |task|
|
158
|
-
|
158
|
+
if task.try?
|
159
|
+
@worker.new(qin, qout, qerr, inherited_env).call(task)
|
160
|
+
else
|
161
|
+
qin.finish!(task)
|
162
|
+
end
|
159
163
|
end
|
160
164
|
end
|
161
165
|
|
data/lib/tq/queue.rb
CHANGED
@@ -5,7 +5,11 @@ module TQ
|
|
5
5
|
|
6
6
|
class Queue
|
7
7
|
|
8
|
-
DEFAULT_OPTIONS = {
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
'lease_secs' => 60,
|
10
|
+
'num_tasks' => 1,
|
11
|
+
'max_tries' => -1
|
12
|
+
}
|
9
13
|
|
10
14
|
attr_reader :client, :api
|
11
15
|
def initialize(client, api, options={})
|
@@ -25,6 +29,10 @@ module TQ
|
|
25
29
|
options({'name' => _})
|
26
30
|
end
|
27
31
|
|
32
|
+
def option(key)
|
33
|
+
@options[key]
|
34
|
+
end
|
35
|
+
|
28
36
|
def lease!(opts={})
|
29
37
|
opts = @options.merge(opts)
|
30
38
|
results = client.execute!(
|
@@ -86,7 +94,15 @@ module TQ
|
|
86
94
|
private
|
87
95
|
|
88
96
|
def new_task(t)
|
89
|
-
Task.new(
|
97
|
+
Task.new(
|
98
|
+
self,
|
99
|
+
t['id'],
|
100
|
+
timestamp_time(t['leaseTimestamp']),
|
101
|
+
t['retry_count'],
|
102
|
+
t['tag'],
|
103
|
+
decode(t.payloadBase64),
|
104
|
+
t
|
105
|
+
)
|
90
106
|
end
|
91
107
|
|
92
108
|
def timestamp_time(t)
|
@@ -103,7 +119,7 @@ module TQ
|
|
103
119
|
|
104
120
|
end
|
105
121
|
|
106
|
-
class Task < Struct.new(:queue, :id, :expires, :payload, :raw)
|
122
|
+
class Task < Struct.new(:queue, :id, :expires, :tries, :tag, :payload, :raw)
|
107
123
|
|
108
124
|
def initialize(*args)
|
109
125
|
super
|
@@ -134,6 +150,11 @@ module TQ
|
|
134
150
|
self.expires < @clock.now
|
135
151
|
end
|
136
152
|
|
153
|
+
def try?
|
154
|
+
max = self.queue.option('max_tries')
|
155
|
+
return (max == -1 or self.tries < max)
|
156
|
+
end
|
157
|
+
|
137
158
|
end
|
138
159
|
|
139
160
|
end
|
data/lib/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -26,18 +26,33 @@ module TestUtils
|
|
26
26
|
attr_reader :project, :queue
|
27
27
|
def initialize(project,queue)
|
28
28
|
@project, @queue = project, queue
|
29
|
+
@service_auth = false
|
29
30
|
end
|
30
31
|
|
31
32
|
def auth_files(secrets,creds)
|
32
33
|
@secrets_file, @creds_file = secrets, creds
|
34
|
+
@service_auth = false
|
35
|
+
return self
|
36
|
+
end
|
37
|
+
|
38
|
+
def service_auth_files(issuer,p12)
|
39
|
+
@secrets_issuer, @secrets_p12 = issuer, p12
|
40
|
+
@service_auth = true
|
33
41
|
return self
|
34
42
|
end
|
35
43
|
|
36
44
|
def authorized_client
|
37
|
-
|
38
|
-
|
45
|
+
@authorized_client ||= (
|
46
|
+
if @service_auth
|
47
|
+
TQ::App.new('test_app',nil).service_auth!(
|
48
|
+
File.read(@secrets_issuer).chomp, @secrets_p12
|
49
|
+
)
|
50
|
+
else
|
51
|
+
TQ::App.new('test_app',nil).auth!(@secrets_file, @creds_file)
|
52
|
+
end
|
53
|
+
)
|
39
54
|
end
|
40
|
-
|
55
|
+
|
41
56
|
# Note: inaccurate, don't use
|
42
57
|
def peek()
|
43
58
|
client, api = authorized_client
|
data/test/test_run.rb
CHANGED
@@ -39,7 +39,7 @@ class AppRunTests < Minitest::Spec
|
|
39
39
|
|
40
40
|
|
41
41
|
def queue_helper(project,queue)
|
42
|
-
TestUtils::QueueHelper.new(project,queue).
|
42
|
+
TestUtils::QueueHelper.new(project,queue).service_auth_files(SERVICE_ISSUER_FILE, SERVICE_P12_FILE)
|
43
43
|
end
|
44
44
|
|
45
45
|
def tasks_on_queue(project,queue)
|
@@ -54,6 +54,10 @@ class AppRunTests < Minitest::Spec
|
|
54
54
|
q = queue_helper(project,queue)
|
55
55
|
tasks.each do |task| q.push!(task) end
|
56
56
|
end
|
57
|
+
|
58
|
+
def service_run!(app)
|
59
|
+
app.service_run! File.read(SERVICE_ISSUER_FILE).chomp, SERVICE_P12_FILE
|
60
|
+
end
|
57
61
|
|
58
62
|
|
59
63
|
describe "run!" do
|
@@ -113,7 +117,8 @@ class AppRunTests < Minitest::Spec
|
|
113
117
|
app = TQ::App.new('test_app/0.0.0', mock_handler_class)
|
114
118
|
.project(TASKQUEUE_PROJECT_ID)
|
115
119
|
.stdin({ 'name' => 'test', 'num_tasks' => expected_calls, 'lease_secs' => TASKQUEUE_LEASE_SECS })
|
116
|
-
app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
120
|
+
# app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
121
|
+
service_run! app
|
117
122
|
|
118
123
|
# assertions
|
119
124
|
assert_equal expected_calls, actual_calls,
|
@@ -141,8 +146,9 @@ class AppRunTests < Minitest::Spec
|
|
141
146
|
app = TQ::App.new('test_app/0.0.0', DoNothingWorker)
|
142
147
|
.project(TASKQUEUE_PROJECT_ID)
|
143
148
|
.stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS })
|
144
|
-
app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
145
|
-
|
149
|
+
# app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
150
|
+
service_run! app
|
151
|
+
|
146
152
|
sleep TASKQUEUE_LEASE_SECS + 1
|
147
153
|
actual_tasks = clear_queue!(TASKQUEUE_PROJECT_ID,'test')
|
148
154
|
|
@@ -182,7 +188,8 @@ class AppRunTests < Minitest::Spec
|
|
182
188
|
.project(TASKQUEUE_PROJECT_ID)
|
183
189
|
.stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS })
|
184
190
|
.stdout({ 'name' => 'log' })
|
185
|
-
app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
191
|
+
# app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
192
|
+
service_run! app
|
186
193
|
|
187
194
|
sleep TASKQUEUE_LEASE_SECS + 1
|
188
195
|
actual_output_tasks = clear_queue!(TASKQUEUE_PROJECT_ID,'log')
|
@@ -228,10 +235,119 @@ class AppRunTests < Minitest::Spec
|
|
228
235
|
app = TQ::App.new('test_app/0.0.0', ExtendWorker)
|
229
236
|
.project(TASKQUEUE_PROJECT_ID)
|
230
237
|
.stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS + 2 })
|
231
|
-
app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
238
|
+
# app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
|
239
|
+
service_run! app
|
232
240
|
|
233
241
|
end
|
234
242
|
|
243
|
+
it 'should retry tasks indefinitely by default' do
|
244
|
+
|
245
|
+
# setup
|
246
|
+
expected_tasks = [
|
247
|
+
{ 'What is your name?' => 'Sir Lancelot', 'What is your quest?' => 'To seek the holy grail', 'What is your favorite color?' => 'blue' }
|
248
|
+
]
|
249
|
+
push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
|
250
|
+
|
251
|
+
# expectations
|
252
|
+
mock_handler_class = MiniTest::Mock.new
|
253
|
+
mock_handler = MiniTest::Mock.new
|
254
|
+
|
255
|
+
## expect constructor receives task queue as first param
|
256
|
+
expected_calls = 3
|
257
|
+
(0...expected_calls).each do
|
258
|
+
mock_handler_class.expect(:new, mock_handler) do |*args|
|
259
|
+
args.first.respond_to?('finish!')
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
## expect :call for each queued task up to expected_calls
|
264
|
+
actual_calls = 0
|
265
|
+
(0...expected_calls).each do
|
266
|
+
mock_handler.expect(:call, true) do |actual_task|
|
267
|
+
actual_calls += 1
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# execution
|
272
|
+
app = TQ::App.new('test_app/0.0.0', mock_handler_class)
|
273
|
+
.project(TASKQUEUE_PROJECT_ID)
|
274
|
+
.stdin({ 'name' => 'test',
|
275
|
+
'num_tasks' => 1,
|
276
|
+
'lease_secs' => TASKQUEUE_LEASE_SECS
|
277
|
+
})
|
278
|
+
.stdout({ 'name' => 'log' })
|
279
|
+
|
280
|
+
service_run! app
|
281
|
+
sleep TASKQUEUE_LEASE_SECS + 1
|
282
|
+
service_run! app
|
283
|
+
sleep TASKQUEUE_LEASE_SECS + 1
|
284
|
+
service_run! app
|
285
|
+
|
286
|
+
# assertion
|
287
|
+
|
288
|
+
assert_equal expected_calls, actual_calls,
|
289
|
+
"Expected #{expected_calls} worker calls, was #{actual_calls}"
|
290
|
+
|
291
|
+
mock_handler_class.verify
|
292
|
+
mock_handler.verify
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should only run if current task retry count is less than queue max_tries' do
|
297
|
+
|
298
|
+
# setup
|
299
|
+
expected_tasks = [
|
300
|
+
{ 'What is your name?' => 'Sir Lancelot', 'What is your quest?' => 'To seek the holy grail', 'What is your favorite color?' => 'blue' }
|
301
|
+
]
|
302
|
+
push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
|
303
|
+
|
304
|
+
# expectations
|
305
|
+
mock_handler_class = MiniTest::Mock.new
|
306
|
+
mock_handler = MiniTest::Mock.new
|
307
|
+
|
308
|
+
## expect constructor receives task queue as first param
|
309
|
+
max_tries = 2
|
310
|
+
expected_calls = max_tries
|
311
|
+
(0...expected_calls).each do
|
312
|
+
mock_handler_class.expect(:new, mock_handler) do |*args|
|
313
|
+
args.first.respond_to?('finish!')
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
## expect :call for each queued task up to expected_calls
|
318
|
+
actual_calls = 0
|
319
|
+
(0...max_tries).each do
|
320
|
+
mock_handler.expect(:call, true) do |actual_task|
|
321
|
+
actual_calls += 1
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# execution
|
326
|
+
app = TQ::App.new('test_app/0.0.0', mock_handler_class)
|
327
|
+
.project(TASKQUEUE_PROJECT_ID)
|
328
|
+
.stdin({ 'name' => 'test',
|
329
|
+
'num_tasks' => 1,
|
330
|
+
'lease_secs' => TASKQUEUE_LEASE_SECS,
|
331
|
+
'max_tries' => max_tries
|
332
|
+
})
|
333
|
+
.stdout({ 'name' => 'log' })
|
334
|
+
|
335
|
+
service_run! app
|
336
|
+
sleep TASKQUEUE_LEASE_SECS + 1
|
337
|
+
service_run! app
|
338
|
+
sleep TASKQUEUE_LEASE_SECS + 1
|
339
|
+
service_run! app
|
340
|
+
|
341
|
+
# assertion
|
342
|
+
assert_equal expected_calls, actual_calls,
|
343
|
+
"Expected #{expected_calls} worker calls, was #{actual_calls}"
|
344
|
+
|
345
|
+
mock_handler_class.verify
|
346
|
+
mock_handler.verify
|
347
|
+
|
348
|
+
end
|
349
|
+
|
350
|
+
|
235
351
|
end
|
236
352
|
|
237
353
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Gjertsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-api-client
|
@@ -91,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
91
|
version: '0'
|
92
92
|
requirements: []
|
93
93
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.
|
94
|
+
rubygems_version: 2.5.1
|
95
95
|
signing_key:
|
96
96
|
specification_version: 4
|
97
97
|
summary: Ruby client for Google App Engine TaskQueue (REST API)
|