tq 0.1.6 → 0.2.1
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.
- 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)
|