tq 0.2.1 → 0.3.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.
@@ -1,50 +1,18 @@
1
1
  require 'fileutils'
2
2
  require_relative './helper'
3
- require_relative '../lib/tq/app'
3
+ require_relative '../lib/tq'
4
4
 
5
5
  def setup_logger!(name)
6
6
  TestUtils.setup_logger(name)
7
7
  end
8
8
 
9
- def delete_credentials!
10
- FileUtils.rm_f(CREDENTIALS_FILE)
11
- end
12
-
13
- # for installed app auth
14
- CLIENT_SECRETS_FILE = File.expand_path('../config/secrets/test/client_secrets.json', File.dirname(__FILE__))
15
- CREDENTIALS_FILE = File.expand_path("../config/secrets/test/#{File.basename(__FILE__,'.rb')}-oauth2.json", File.dirname(__FILE__))
16
-
17
- # for service account auth
18
- SERVICE_ISSUER_FILE = File.expand_path('../config/secrets/test/issuer', File.dirname(__FILE__))
19
- SERVICE_P12_FILE = File.expand_path('../config/secrets/test/client.p12', File.dirname(__FILE__))
9
+ SERVICE_ACCOUNT_FILE = File.expand_path(
10
+ '../config/secrets/test/service_account.json',
11
+ File.dirname(__FILE__)
12
+ )
20
13
 
21
14
  describe TQ::App do
22
15
 
23
- describe "auth" do
24
-
25
- before do
26
- setup_logger!('auth')
27
- delete_credentials!
28
- end
29
-
30
- it "should authorize without cached credentials" do
31
- app = TQ::App.new('test_app/0.0.0', nil)
32
- app.auth! CLIENT_SECRETS_FILE
33
- assert true
34
- end
35
-
36
- # Note: browser window should only appear once for this test
37
- # Not sure if it's possible to assert this
38
- it "should authorize with cached credentials not existing and existing" do
39
- app = TQ::App.new('test_app/0.0.0', nil)
40
- app.auth! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
41
- assert File.exists?(CREDENTIALS_FILE)
42
- app.auth! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
43
- assert File.exists?(CREDENTIALS_FILE)
44
- end
45
-
46
- end
47
-
48
16
  describe "service auth" do
49
17
 
50
18
  before do
@@ -52,8 +20,8 @@ describe TQ::App do
52
20
  end
53
21
 
54
22
  it "should authorize service account" do
55
- app = TQ::App.new('test_app/0.0.0', nil)
56
- app.service_auth!(File.read(SERVICE_ISSUER_FILE).chomp, SERVICE_P12_FILE)
23
+ app = TQ::App.new(nil, nil, nil, nil)
24
+ app.service_account_client(File.read(SERVICE_ACCOUNT_FILE).chomp)
57
25
  assert true
58
26
  end
59
27
 
@@ -7,8 +7,7 @@
7
7
  require 'logger'
8
8
 
9
9
  require_relative './helper'
10
- require_relative '../lib/tq/app'
11
- require_relative '../lib/tq/queue'
10
+ require_relative '../lib/tq'
12
11
  require_relative '../lib/tq/logger'
13
12
 
14
13
  def setup_test_logger!
@@ -18,26 +17,44 @@ end
18
17
 
19
18
  class LoggerTests < Minitest::Spec
20
19
 
21
- # for installed app auth
22
- CLIENT_SECRETS_FILE = File.expand_path(
23
- '../config/secrets/test/client_secrets.json', File.dirname(__FILE__)
24
- )
25
- CREDENTIALS_FILE = File.expand_path(
26
- "../config/secrets/test/#{File.basename(__FILE__,'.rb')}-oauth2.json",
27
- File.dirname(__FILE__)
20
+ # for service account auth
21
+ SERVICE_ACCOUNT_FILE = File.expand_path(
22
+ '../config/secrets/test/service_account.json', File.dirname(__FILE__)
28
23
  )
29
24
 
30
25
  # task queue constants
31
- TASKQUEUE_PROJECT_ID = File.read(
26
+ PROJECT_ID = File.read(
32
27
  File.expand_path('../config/secrets/test/project_id', File.dirname(__FILE__))
33
28
  ).chomp
34
-
35
- TASKQUEUE_TEST_QUEUE = 'log'
29
+
30
+ LOCATION = 'us-central1'
31
+ TASKQUEUE_LEASE_SECS = 2
32
+ TEST_QUEUE = 'log'
36
33
 
37
34
  def test_logger
38
35
  @test_logger ||= TestUtils.current_logger
39
36
  end
40
37
 
38
+ def queue_helper
39
+ TestUtils::QueueHelper.new(
40
+ TQ::QueueSpec.new( PROJECT_ID, LOCATION, TEST_QUEUE ),
41
+ SERVICE_ACCOUNT_FILE
42
+ )
43
+ end
44
+
45
+ def clear_queue!
46
+ queue_helper.clear!
47
+ end
48
+
49
+ def queue_spec(max_tasks)
50
+ TQ::QueueSpec.new( PROJECT_ID, LOCATION, TEST_QUEUE,
51
+ max_tasks: max_tasks, lease_duration: "#{TASKQUEUE_LEASE_SECS}s")
52
+ end
53
+
54
+ def service_account_client
55
+ TQ::ServiceAccount.client(SERVICE_ACCOUNT_FILE)
56
+ end
57
+
41
58
  def assert_logged( exps, acts )
42
59
  errs = []
43
60
  unless (a = exps.length) == (b = acts.length)
@@ -86,26 +103,17 @@ class LoggerTests < Minitest::Spec
86
103
  end
87
104
  end
88
105
 
89
- def queue_helper(project,queue)
90
- TestUtils::QueueHelper.new(project,queue).auth_files(CLIENT_SECRETS_FILE, CREDENTIALS_FILE)
91
- end
92
-
93
- def clear_queue!(project,queue)
94
- queue_helper(project,queue).clear!
95
- end
96
-
97
106
  def verify_logged_messages_to_level!(expected_messages, minlevel)
98
- actual_messages = queue_helper(TASKQUEUE_PROJECT_ID, TASKQUEUE_TEST_QUEUE).all_payloads_and_tags!
99
- $stderr.puts actual_messages.inspect
107
+ actual_messages = queue_helper.messages!
100
108
 
101
109
  selected_messages = expected_messages.select { |msg| msg[:level] >= minlevel }
102
110
 
103
111
  assert_logged( selected_messages,
104
- actual_messages.map { |msg| msg[:payload] }
112
+ actual_messages.map { |m| JSON.load(m.payload) }
105
113
  )
106
114
 
107
115
  assert_logged_tags( selected_messages,
108
- actual_messages.map { |msg| msg[:tag] }
116
+ actual_messages.map { |m| m.tag }
109
117
  )
110
118
  end
111
119
 
@@ -114,11 +122,8 @@ class LoggerTests < Minitest::Spec
114
122
  # you should just eyeball it in the $stderr output.
115
123
 
116
124
  def setup
117
- clear_queue!(TASKQUEUE_PROJECT_ID, TASKQUEUE_TEST_QUEUE)
118
-
119
- app = TQ::App.new('test_app/0.0.0', nil)
120
- @queue = TQ::Queue.new( *app.auth!(CLIENT_SECRETS_FILE, CREDENTIALS_FILE) )
121
- .options({ 'project' => TASKQUEUE_PROJECT_ID, 'name' => TASKQUEUE_TEST_QUEUE })
125
+ clear_queue!
126
+ @queue = TQ::Queue.new( service_account_client, queue_spec(1) )
122
127
  end
123
128
 
124
129
  it 'default logger should log to queue at warn level' do
@@ -5,7 +5,7 @@
5
5
  # along with other secrets files (see below).
6
6
 
7
7
  require_relative './helper'
8
- require_relative '../lib/tq/app'
8
+ require_relative '../lib/tq'
9
9
 
10
10
  def setup_test_logger!
11
11
  TestUtils.setup_logger( File.basename(__FILE__,'.rb') )
@@ -13,50 +13,44 @@ end
13
13
 
14
14
  class AppRunTests < Minitest::Spec
15
15
 
16
- # for installed app auth
17
- CLIENT_SECRETS_FILE = File.expand_path(
18
- '../config/secrets/test/client_secrets.json', File.dirname(__FILE__)
19
- )
20
- CREDENTIALS_FILE = File.expand_path(
21
- "../config/secrets/test/#{File.basename(__FILE__,'.rb')}-oauth2.json",
22
- File.dirname(__FILE__)
23
- )
24
-
25
- # for service account auth -- not quite working
26
- SERVICE_ISSUER_FILE = File.expand_path(
27
- '../config/secrets/test/issuer', File.dirname(__FILE__)
28
- )
29
- SERVICE_P12_FILE = File.expand_path(
30
- '../config/secrets/test/client.p12', File.dirname(__FILE__)
16
+ # for service account auth
17
+ SERVICE_ACCOUNT_FILE = File.expand_path(
18
+ '../config/secrets/test/service_account.json', File.dirname(__FILE__)
31
19
  )
32
20
 
33
21
  # task queue constants
34
- TASKQUEUE_PROJECT_ID = File.read(
22
+ PROJECT_ID = File.read(
35
23
  File.expand_path('../config/secrets/test/project_id', File.dirname(__FILE__))
36
24
  ).chomp
25
+
26
+ LOCATION = 'us-central1'
37
27
 
38
28
  TASKQUEUE_LEASE_SECS = 2
39
29
 
40
30
 
41
- def queue_helper(project,queue)
42
- TestUtils::QueueHelper.new(project,queue).service_auth_files(SERVICE_ISSUER_FILE, SERVICE_P12_FILE)
43
- end
44
-
45
- def tasks_on_queue(project,queue)
46
- queue_helper(project,queue).list
31
+ def queue_helper(queue)
32
+ TestUtils::QueueHelper.new(
33
+ TQ::QueueSpec.new( PROJECT_ID, LOCATION, queue ),
34
+ SERVICE_ACCOUNT_FILE
35
+ )
47
36
  end
48
37
 
49
- def clear_queue!(project,queue)
50
- queue_helper(project,queue).clear!
38
+ def clear_queue!(queue)
39
+ queue_helper(queue).clear!
51
40
  end
52
41
 
53
- def push_tasks!(project,queue,tasks)
54
- q = queue_helper(project,queue)
42
+ def push_tasks!(queue,tasks)
43
+ q = queue_helper(queue)
55
44
  tasks.each do |task| q.push!(task) end
56
45
  end
57
46
 
58
- def service_run!(app)
59
- app.service_run! File.read(SERVICE_ISSUER_FILE).chomp, SERVICE_P12_FILE
47
+ def queue_spec(name, max_tasks)
48
+ TQ::QueueSpec.new(PROJECT_ID, LOCATION, name,
49
+ max_tasks: max_tasks, lease_duration: "#{TASKQUEUE_LEASE_SECS}s")
50
+ end
51
+
52
+ def run!(app)
53
+ app.call SERVICE_ACCOUNT_FILE
60
54
  end
61
55
 
62
56
 
@@ -64,18 +58,13 @@ class AppRunTests < Minitest::Spec
64
58
 
65
59
  before do
66
60
  sleep TASKQUEUE_LEASE_SECS + 1 # to wait for lease expiry from previous test
67
- clear_queue!(TASKQUEUE_PROJECT_ID,'test')
68
- clear_queue!(TASKQUEUE_PROJECT_ID,'log')
61
+ clear_queue!('test')
62
+ clear_queue!('log')
69
63
  end
70
64
 
71
65
  it "should setup clearing the queue" do
72
- cleared = clear_queue!(TASKQUEUE_PROJECT_ID,'test')
73
- assert_equal 0, n = cleared.length,
74
- "Expected no tasks on queue, #{n < 2 ? 'was' : 'were'} #{n}"
75
-
76
- # unfortunately, queue peeks are horribly inaccurate right now.
77
- # assert_equal 0, n = tasks_on_queue(TASKQUEUE_PROJECT_ID,'test').length,
78
- # "Expected no tasks on queue, #{n < 2 ? 'was' : 'were'} #{n}"
66
+ cleared = clear_queue!('test')
67
+ assert true
79
68
  end
80
69
 
81
70
  it "worker should receive input queue and :call with each task on the queue up to the specified number" do
@@ -87,7 +76,7 @@ class AppRunTests < Minitest::Spec
87
76
  { 'What is your name?' => 'Galahad', 'What is your quest?' => 'To seek the grail', 'What is your favorite color?' => ['blue','yellow'] },
88
77
  { 'What is your name?' => 'Arthur', 'What is your quest?' => 'To seek the holy grail', 'What is the air-speed velocity of an unladen swallow?' => 'African or European swallow?' }
89
78
  ]
90
- push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
79
+ push_tasks!('test', expected_tasks)
91
80
 
92
81
  # expectations
93
82
  mock_handler_class = MiniTest::Mock.new
@@ -114,11 +103,8 @@ class AppRunTests < Minitest::Spec
114
103
  end
115
104
 
116
105
  # execution
117
- app = TQ::App.new('test_app/0.0.0', mock_handler_class)
118
- .project(TASKQUEUE_PROJECT_ID)
119
- .stdin({ 'name' => 'test', 'num_tasks' => expected_calls, 'lease_secs' => TASKQUEUE_LEASE_SECS })
120
- # app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
121
- service_run! app
106
+ app = TQ::App.new(mock_handler_class, queue_spec('test', expected_calls))
107
+ run! app
122
108
 
123
109
  # assertions
124
110
  assert_equal expected_calls, actual_calls,
@@ -129,13 +115,14 @@ class AppRunTests < Minitest::Spec
129
115
 
130
116
  end
131
117
 
118
+
132
119
  it 'should put task back on input queue after lease_secs, if not finished' do
133
120
 
134
121
  # setup
135
122
  expected_tasks = [
136
123
  { 'What is your name?' => 'Sir Lancelot', 'What is your quest?' => 'To seek the holy grail', 'What is your favorite color?' => 'blue' }
137
124
  ]
138
- push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
125
+ push_tasks!('test', expected_tasks)
139
126
 
140
127
  class DoNothingWorker
141
128
  def initialize(*args); end
@@ -143,25 +130,16 @@ class AppRunTests < Minitest::Spec
143
130
  end
144
131
 
145
132
  # execution
146
- app = TQ::App.new('test_app/0.0.0', DoNothingWorker)
147
- .project(TASKQUEUE_PROJECT_ID)
148
- .stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS })
149
- # app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
150
- service_run! app
133
+ app = TQ::App.new(DoNothingWorker, queue_spec('test', 1))
134
+ run! app
151
135
 
152
136
  sleep TASKQUEUE_LEASE_SECS + 1
153
- actual_tasks = clear_queue!(TASKQUEUE_PROJECT_ID,'test')
137
+ actual_tasks = clear_queue!('test')
154
138
 
155
- ## queue peeks are inaccurate right now...
156
- # actual_tasks = tasks_on_queue(TASKQUEUE_PROJECT_ID,'test')
157
-
158
- ## assertion
139
+ # assertion
159
140
  assert_equal a = expected_tasks.length, b = actual_tasks.length,
160
141
  "Expected #{a} #{a == 1 ? 'task' : 'tasks'} on queue, #{b < 2 ? 'was' : 'were'} #{b}"
161
142
 
162
- assert (n = actual_tasks.first['retry_count']) > 0,
163
- "Expected >0 lease retry count, #{n < 2 ? 'was' : 'were'} #{n}"
164
-
165
143
  end
166
144
 
167
145
  it 'should be able to push to queue from within worker' do
@@ -170,7 +148,7 @@ class AppRunTests < Minitest::Spec
170
148
  expected_tasks = [
171
149
  { 'What is your name?' => 'Sir Lancelot', 'What is your quest?' => 'To seek the holy grail', 'What is your favorite color?' => 'blue' }
172
150
  ]
173
- push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
151
+ push_tasks!('test', expected_tasks)
174
152
 
175
153
  class RelayWorker
176
154
  def initialize(*args)
@@ -184,16 +162,12 @@ class AppRunTests < Minitest::Spec
184
162
  end
185
163
 
186
164
  # execution
187
- app = TQ::App.new('test_app/0.0.0', RelayWorker)
188
- .project(TASKQUEUE_PROJECT_ID)
189
- .stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS })
190
- .stdout({ 'name' => 'log' })
191
- # app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
192
- service_run! app
165
+ app = TQ::App.new(RelayWorker, queue_spec('test', 1), queue_out: queue_spec('log',1))
166
+ run! app
193
167
 
194
168
  sleep TASKQUEUE_LEASE_SECS + 1
195
- actual_output_tasks = clear_queue!(TASKQUEUE_PROJECT_ID,'log')
196
- actual_input_tasks = clear_queue!(TASKQUEUE_PROJECT_ID,'test')
169
+ actual_output_tasks = clear_queue!('log')
170
+ actual_input_tasks = clear_queue!('test')
197
171
 
198
172
  # assertion
199
173
 
@@ -203,153 +177,48 @@ class AppRunTests < Minitest::Spec
203
177
  assert_equal a = expected_tasks.length, b = actual_output_tasks.length,
204
178
  "Expected #{a} #{a == 1 ? 'task' : 'tasks'} on output queue, #{b < 2 ? 'was' : 'were'} #{b}"
205
179
 
180
+
206
181
  end
207
182
 
208
183
  it 'should extend a task lease if extended before lease expires' do
209
-
210
- refute true, "Extending task leases does not currently work"
211
184
 
212
185
  # setup
213
186
  expected_tasks = [
214
187
  { 'What is your name?' => 'Sir Lancelot', 'What is your quest?' => 'To seek the holy grail', 'What is your favorite color?' => 'blue' }
215
188
  ]
216
- push_tasks!(TASKQUEUE_PROJECT_ID,'test', expected_tasks)
189
+ push_tasks!('test', expected_tasks)
217
190
 
218
191
  class ExtendWorker
192
+ include MiniTest::Assertions
193
+
194
+ attr_accessor :assertions
219
195
  def initialize(*args)
220
196
  @stdin = args.first
197
+ @assertions = 0
221
198
  end
222
199
 
223
200
  def call(task)
224
- $stderr.puts "ExtendWorker - task #{ task.raw.inspect }"
225
201
  ttl = task.lease_remaining
226
- # sleep( ttl - 0.5 )
227
- task = @stdin.extend!(task)
202
+ sleep( ttl - 0.5 )
203
+ task = task.extend!('3s')
228
204
  ttl2 = task.lease_remaining
229
205
  $stderr.puts "ExtendWorker - ttl before extend: #{ttl}"
230
206
  $stderr.puts "ExtendWorker - ttl after extend: #{ttl2}"
207
+ assert_in_delta( 2.5, ttl2, 0.07,
208
+ "Expected to be approximately 2.5s"
209
+ )
231
210
  end
232
211
  end
233
212
 
234
213
  # execution
235
- app = TQ::App.new('test_app/0.0.0', ExtendWorker)
236
- .project(TASKQUEUE_PROJECT_ID)
237
- .stdin({ 'name' => 'test', 'num_tasks' => 1, 'lease_secs' => TASKQUEUE_LEASE_SECS + 2 })
238
- # app.run! CLIENT_SECRETS_FILE, CREDENTIALS_FILE
239
- service_run! app
240
-
241
- end
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' })
214
+ app = TQ::App.new(ExtendWorker, queue_spec('test', 1))
215
+ run! app
279
216
 
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
217
  end
349
218
 
350
-
351
219
  end
352
220
 
353
221
  end
354
222
 
355
223
  setup_test_logger!
224
+