que 0.11.3 → 2.2.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.
Files changed (114) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/tests.yml +51 -0
  3. data/.gitignore +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +502 -97
  6. data/Dockerfile +20 -0
  7. data/LICENSE.txt +1 -1
  8. data/README.md +205 -59
  9. data/auto/dev +21 -0
  10. data/auto/pre-push-hook +30 -0
  11. data/auto/psql +9 -0
  12. data/auto/test +5 -0
  13. data/auto/test-postgres-14 +17 -0
  14. data/bin/que +8 -81
  15. data/docker-compose.yml +47 -0
  16. data/docs/README.md +881 -0
  17. data/lib/que/active_job/extensions.rb +114 -0
  18. data/lib/que/active_record/connection.rb +51 -0
  19. data/lib/que/active_record/model.rb +48 -0
  20. data/lib/que/command_line_interface.rb +259 -0
  21. data/lib/que/connection.rb +198 -0
  22. data/lib/que/connection_pool.rb +78 -0
  23. data/lib/que/job.rb +210 -103
  24. data/lib/que/job_buffer.rb +255 -0
  25. data/lib/que/job_methods.rb +176 -0
  26. data/lib/que/listener.rb +176 -0
  27. data/lib/que/locker.rb +507 -0
  28. data/lib/que/metajob.rb +47 -0
  29. data/lib/que/migrations/4/down.sql +48 -0
  30. data/lib/que/migrations/4/up.sql +267 -0
  31. data/lib/que/migrations/5/down.sql +73 -0
  32. data/lib/que/migrations/5/up.sql +76 -0
  33. data/lib/que/migrations/6/down.sql +8 -0
  34. data/lib/que/migrations/6/up.sql +8 -0
  35. data/lib/que/migrations/7/down.sql +5 -0
  36. data/lib/que/migrations/7/up.sql +13 -0
  37. data/lib/que/migrations.rb +37 -18
  38. data/lib/que/poller.rb +274 -0
  39. data/lib/que/rails/railtie.rb +12 -0
  40. data/lib/que/result_queue.rb +35 -0
  41. data/lib/que/sequel/model.rb +52 -0
  42. data/lib/que/utils/assertions.rb +62 -0
  43. data/lib/que/utils/constantization.rb +19 -0
  44. data/lib/que/utils/error_notification.rb +68 -0
  45. data/lib/que/utils/freeze.rb +20 -0
  46. data/lib/que/utils/introspection.rb +50 -0
  47. data/lib/que/utils/json_serialization.rb +21 -0
  48. data/lib/que/utils/logging.rb +79 -0
  49. data/lib/que/utils/middleware.rb +46 -0
  50. data/lib/que/utils/queue_management.rb +18 -0
  51. data/lib/que/utils/ruby2_keywords.rb +19 -0
  52. data/lib/que/utils/transactions.rb +34 -0
  53. data/lib/que/version.rb +5 -1
  54. data/lib/que/worker.rb +145 -149
  55. data/lib/que.rb +103 -159
  56. data/que.gemspec +17 -4
  57. data/scripts/docker-entrypoint +14 -0
  58. data/scripts/test +6 -0
  59. metadata +59 -95
  60. data/.rspec +0 -2
  61. data/.travis.yml +0 -17
  62. data/Gemfile +0 -24
  63. data/docs/advanced_setup.md +0 -106
  64. data/docs/customizing_que.md +0 -200
  65. data/docs/error_handling.md +0 -47
  66. data/docs/inspecting_the_queue.md +0 -114
  67. data/docs/logging.md +0 -50
  68. data/docs/managing_workers.md +0 -80
  69. data/docs/migrating.md +0 -30
  70. data/docs/multiple_queues.md +0 -27
  71. data/docs/shutting_down_safely.md +0 -7
  72. data/docs/using_plain_connections.md +0 -41
  73. data/docs/using_sequel.md +0 -31
  74. data/docs/writing_reliable_jobs.md +0 -117
  75. data/lib/generators/que/install_generator.rb +0 -24
  76. data/lib/generators/que/templates/add_que.rb +0 -13
  77. data/lib/que/adapters/active_record.rb +0 -54
  78. data/lib/que/adapters/base.rb +0 -127
  79. data/lib/que/adapters/connection_pool.rb +0 -16
  80. data/lib/que/adapters/pg.rb +0 -21
  81. data/lib/que/adapters/pond.rb +0 -16
  82. data/lib/que/adapters/sequel.rb +0 -20
  83. data/lib/que/railtie.rb +0 -16
  84. data/lib/que/rake_tasks.rb +0 -59
  85. data/lib/que/sql.rb +0 -152
  86. data/spec/adapters/active_record_spec.rb +0 -152
  87. data/spec/adapters/connection_pool_spec.rb +0 -22
  88. data/spec/adapters/pg_spec.rb +0 -41
  89. data/spec/adapters/pond_spec.rb +0 -22
  90. data/spec/adapters/sequel_spec.rb +0 -57
  91. data/spec/gemfiles/Gemfile1 +0 -18
  92. data/spec/gemfiles/Gemfile2 +0 -18
  93. data/spec/spec_helper.rb +0 -118
  94. data/spec/support/helpers.rb +0 -19
  95. data/spec/support/jobs.rb +0 -35
  96. data/spec/support/shared_examples/adapter.rb +0 -37
  97. data/spec/support/shared_examples/multi_threaded_adapter.rb +0 -46
  98. data/spec/travis.rb +0 -23
  99. data/spec/unit/connection_spec.rb +0 -14
  100. data/spec/unit/customization_spec.rb +0 -251
  101. data/spec/unit/enqueue_spec.rb +0 -245
  102. data/spec/unit/helper_spec.rb +0 -12
  103. data/spec/unit/logging_spec.rb +0 -101
  104. data/spec/unit/migrations_spec.rb +0 -84
  105. data/spec/unit/pool_spec.rb +0 -365
  106. data/spec/unit/run_spec.rb +0 -14
  107. data/spec/unit/states_spec.rb +0 -50
  108. data/spec/unit/stats_spec.rb +0 -46
  109. data/spec/unit/transaction_spec.rb +0 -36
  110. data/spec/unit/work_spec.rb +0 -407
  111. data/spec/unit/worker_spec.rb +0 -167
  112. data/tasks/benchmark.rb +0 -3
  113. data/tasks/rspec.rb +0 -14
  114. data/tasks/safe_shutdown.rb +0 -67
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- shared_examples "a multi-threaded Que adapter" do
4
- it_behaves_like "a Que adapter"
5
-
6
- it "should allow multiple threads to check out their own connections" do
7
- one = nil
8
- two = nil
9
-
10
- q1, q2 = Queue.new, Queue.new
11
-
12
- thread = Thread.new do
13
- Que.adapter.checkout do |conn|
14
- q1.push nil
15
- q2.pop
16
- one = conn.object_id
17
- end
18
- end
19
-
20
- Que.adapter.checkout do |conn|
21
- q1.pop
22
- q2.push nil
23
- two = conn.object_id
24
- end
25
-
26
- thread.join
27
- one.should_not == two
28
- end
29
-
30
- it "should allow multiple workers to complete jobs simultaneously" do
31
- BlockJob.enqueue
32
- worker_1 = Que::Worker.new
33
- $q1.pop
34
-
35
- Que::Job.enqueue
36
- DB[:que_jobs].count.should be 2
37
-
38
- worker_2 = Que::Worker.new
39
- sleep_until { worker_2.sleeping? }
40
- DB[:que_jobs].count.should be 1
41
-
42
- $q2.push nil
43
- sleep_until { worker_1.sleeping? }
44
- DB[:que_jobs].count.should be 0
45
- end
46
- end
data/spec/travis.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #!/usr/bin/env ruby
4
-
5
- # Run tests a bunch of times, flush out thread race conditions / errors.
6
- test_runs = if ENV['TESTS']
7
- Integer(ENV['TESTS'])
8
- else
9
- 25
10
- end
11
-
12
-
13
- # I think travis might be pausing jobs, let's try a higher timeout
14
- QUE_TEST_TIMEOUT = 10
15
-
16
- %w( Gemfile spec/gemfiles/Gemfile1 spec/gemfiles/Gemfile2 ).each do |gemfile|
17
- # Install the particular gemfile
18
- system("BUNDLE_GEMFILE=#{gemfile} bundle")
19
- 1.upto(test_runs) do |i|
20
- puts "Test Run #{i}"
21
- exit(-1) if !system("bundle exec rake")
22
- end
23
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Que do
6
- it ".connection= with an unsupported connection should raise an error" do
7
- proc{Que.connection = "ferret"}.should raise_error RuntimeError, /Que connection not recognized: "ferret"/
8
- end
9
-
10
- it ".adapter when no connection has been established should raise an error" do
11
- Que.connection = nil
12
- proc{Que.adapter}.should raise_error RuntimeError, /Que connection not established!/
13
- end
14
- end
@@ -1,251 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- # A few specs to ensure that the ideas given in the customizing_que document
6
- # stay functional.
7
- describe "Customizing Que" do
8
- it "Cron should allow for easy recurring jobs" do
9
- begin
10
- class CronJob < Que::Job
11
- # Default repetition interval in seconds. Can be overridden in
12
- # subclasses. Can use 1.minute if using Rails.
13
- INTERVAL = 60
14
-
15
- attr_reader :start_at, :end_at, :run_again_at, :time_range
16
-
17
- def _run
18
- args = attrs[:args].first
19
- @start_at, @end_at = Time.at(args.delete('start_at')), Time.at(args.delete('end_at'))
20
- @run_again_at = @end_at + self.class::INTERVAL
21
- @time_range = @start_at...@end_at
22
-
23
- super
24
-
25
- args['start_at'] = @end_at.to_f
26
- args['end_at'] = @run_again_at.to_f
27
- self.class.enqueue(args, run_at: @run_again_at)
28
- end
29
- end
30
-
31
- class MyCronJob < CronJob
32
- INTERVAL = 1.5
33
-
34
- def run(args)
35
- $args = args.dup
36
- $time_range = time_range
37
- end
38
- end
39
-
40
- t = (Time.now - 1000).to_f.round(6)
41
- MyCronJob.enqueue :start_at => t, :end_at => t + 1.5, :arg => 4
42
-
43
- $args.should be nil
44
- $time_range.should be nil
45
-
46
- Que::Job.work
47
-
48
- $args.should == {'arg' => 4}
49
- $time_range.begin.to_f.round(6).should be_within(0.000001).of t
50
- $time_range.end.to_f.round(6).should be_within(0.000001).of t + 1.5
51
- $time_range.exclude_end?.should be true
52
-
53
- DB[:que_jobs].get(:run_at).to_f.round(6).should be_within(0.000001).of(t + 3.0)
54
- args = JSON.parse(DB[:que_jobs].get(:args)).first
55
- args.keys.should == ['arg', 'start_at', 'end_at']
56
- args['arg'].should == 4
57
- args['start_at'].should be_within(0.000001).of(t + 1.5)
58
- args['end_at'].should be_within(0.000001).of(t + 3.0)
59
- ensure
60
- $args = nil
61
- $time_range = nil
62
- end
63
- end
64
-
65
- it "Object#delay should allow for simpler job enqueueing" do
66
- begin
67
- class Delayed < Que::Job
68
- def run(receiver, method, args)
69
- Marshal.load(receiver).send method, *Marshal.load(args)
70
- end
71
- end
72
-
73
- class DelayedAction
74
- def initialize(receiver)
75
- @receiver = receiver
76
- end
77
-
78
- def method_missing(method, *args)
79
- Delayed.enqueue Marshal.dump(@receiver), method, Marshal.dump(args)
80
- end
81
- end
82
-
83
- class Object
84
- def delay
85
- DelayedAction.new(self)
86
- end
87
- end
88
-
89
- module MyModule
90
- class << self
91
- def blah
92
- $run = true
93
- end
94
- end
95
- end
96
-
97
- MyModule.delay.blah
98
- Que::Job.work
99
-
100
- $run.should be true
101
- ensure
102
- $run = nil
103
- end
104
- end
105
-
106
- it "QueueClassic-style jobs should be easy" do
107
- begin
108
- class Command < Que::Job
109
- def run(method, *args)
110
- receiver, message = method.split('.')
111
- Object.const_get(receiver).send(message, *args)
112
- end
113
- end
114
-
115
- module MyModule
116
- class << self
117
- def blah(arg)
118
- $value = arg
119
- end
120
- end
121
- end
122
-
123
- Command.enqueue "MyModule.blah", "hello world"
124
- Que::Job.work
125
-
126
- $value.should == "hello world"
127
- ensure
128
- $value = nil
129
- end
130
- end
131
-
132
- describe "retaining deleted jobs" do
133
- before do
134
- Que.execute "CREATE TABLE finished_jobs AS SELECT * FROM que_jobs LIMIT 0"
135
- end
136
-
137
- after do
138
- DB.drop_table? :finished_jobs
139
- end
140
-
141
- it "with a Ruby override" do
142
- class MyJobClass < Que::Job
143
- def destroy
144
- Que.execute "INSERT INTO finished_jobs SELECT * FROM que_jobs WHERE queue = $1::text AND priority = $2::integer AND run_at = $3::timestamptz AND job_id = $4::bigint", @attrs.values_at(:queue, :priority, :run_at, :job_id)
145
- super
146
- end
147
- end
148
-
149
- class MyJob < MyJobClass
150
- end
151
-
152
- MyJob.enqueue 1, 'arg1', :priority => 89
153
- Que::Job.work
154
-
155
- DB[:finished_jobs].count.should == 1
156
- job = DB[:finished_jobs].first
157
- job[:priority].should == 89
158
- JSON.load(job[:args]).should == [1, 'arg1']
159
- end
160
-
161
- it "with a trigger" do
162
- begin
163
- Que.execute <<-SQL
164
- CREATE FUNCTION please_save_my_job()
165
- RETURNS trigger
166
- LANGUAGE plpgsql
167
- AS $$
168
- BEGIN
169
- INSERT INTO finished_jobs SELECT (OLD).*;
170
- RETURN OLD;
171
- END;
172
- $$;
173
- SQL
174
-
175
- Que.execute "CREATE TRIGGER keep_all_my_old_jobs BEFORE DELETE ON que_jobs FOR EACH ROW EXECUTE PROCEDURE please_save_my_job();"
176
-
177
- Que::Job.enqueue 2, 'arg2', :priority => 45
178
- Que::Job.work
179
-
180
- DB[:finished_jobs].count.should == 1
181
- job = DB[:finished_jobs].first
182
- job[:priority].should == 45
183
- JSON.load(job[:args]).should == [2, 'arg2']
184
- ensure
185
- DB.drop_trigger :que_jobs, :keep_all_my_old_jobs, :if_exists => true
186
- DB.drop_function :please_save_my_job, :if_exists => true
187
- end
188
- end
189
- end
190
-
191
- describe "not retrying specific failed jobs" do
192
- before do
193
- Que.execute "CREATE TABLE failed_jobs AS SELECT * FROM que_jobs LIMIT 0"
194
- end
195
-
196
- after do
197
- DB.drop_table? :failed_jobs
198
- end
199
-
200
- it "should be easily achievable with a module" do
201
- begin
202
- module SkipRetries
203
- def run(*args)
204
- super
205
- rescue
206
- sql = <<-SQL
207
- WITH failed AS (
208
- DELETE
209
- FROM que_jobs
210
- WHERE queue = $1::text
211
- AND priority = $2::smallint
212
- AND run_at = $3::timestamptz
213
- AND job_id = $4::bigint
214
- RETURNING *
215
- )
216
- INSERT INTO failed_jobs
217
- SELECT * FROM failed;
218
- SQL
219
-
220
- Que.execute sql, @attrs.values_at(:queue, :priority, :run_at, :job_id)
221
-
222
- raise
223
- end
224
- end
225
-
226
- class SkipRetryJob < Que::Job
227
- prepend SkipRetries
228
-
229
- def run(*args)
230
- $retry_job_args = args
231
- raise "Fail!"
232
- end
233
- end
234
-
235
- SkipRetryJob.enqueue 1, 'arg1', :other_arg => 'blah'
236
- Que::Job.work
237
-
238
- $retry_job_args.should == [1, 'arg1', {'other_arg' => 'blah'}]
239
-
240
- DB[:que_jobs].count.should == 0
241
- DB[:failed_jobs].count.should == 1
242
-
243
- job = DB[:failed_jobs].first
244
- JSON.parse(job[:args]).should == [1, 'arg1', {'other_arg' => 'blah'}]
245
- job[:job_class].should == 'SkipRetryJob'
246
- ensure
247
- $retry_job_args = nil
248
- end
249
- end
250
- end
251
- end
@@ -1,245 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Que::Job, '.enqueue' do
6
- it "should be able to queue a job" do
7
- DB[:que_jobs].count.should be 0
8
- result = Que::Job.enqueue
9
- DB[:que_jobs].count.should be 1
10
-
11
- result.should be_an_instance_of Que::Job
12
- result.attrs[:queue].should == ''
13
- result.attrs[:priority].should == 100
14
- result.attrs[:args].should == []
15
-
16
- job = DB[:que_jobs].first
17
- job[:queue].should == ''
18
- job[:priority].should be 100
19
- job[:run_at].should be_within(3).of Time.now
20
- job[:job_class].should == "Que::Job"
21
- JSON.load(job[:args]).should == []
22
- end
23
-
24
- it "should be aliased to .queue" do
25
- DB[:que_jobs].count.should be 0
26
- suppress_warnings { Que::Job.queue }
27
- DB[:que_jobs].count.should be 1
28
- end
29
-
30
- it "should be able to queue a job with arguments" do
31
- DB[:que_jobs].count.should be 0
32
- Que::Job.enqueue 1, 'two'
33
- DB[:que_jobs].count.should be 1
34
-
35
- job = DB[:que_jobs].first
36
- job[:queue].should == ''
37
- job[:priority].should be 100
38
- job[:run_at].should be_within(3).of Time.now
39
- job[:job_class].should == "Que::Job"
40
- JSON.load(job[:args]).should == [1, 'two']
41
- end
42
-
43
- it "should be able to queue a job with complex arguments" do
44
- DB[:que_jobs].count.should be 0
45
- Que::Job.enqueue 1, 'two', :string => "string",
46
- :integer => 5,
47
- :array => [1, "two", {:three => 3}],
48
- :hash => {:one => 1, :two => 'two', :three => [3]}
49
-
50
- DB[:que_jobs].count.should be 1
51
-
52
- job = DB[:que_jobs].first
53
- job[:queue].should == ''
54
- job[:priority].should be 100
55
- job[:run_at].should be_within(3).of Time.now
56
- job[:job_class].should == "Que::Job"
57
- JSON.load(job[:args]).should == [
58
- 1,
59
- 'two',
60
- {
61
- 'string' => 'string',
62
- 'integer' => 5,
63
- 'array' => [1, "two", {"three" => 3}],
64
- 'hash' => {'one' => 1, 'two' => 'two', 'three' => [3]}
65
- }
66
- ]
67
- end
68
-
69
- it "should be able to queue a job with a specific time to run" do
70
- DB[:que_jobs].count.should be 0
71
- Que::Job.enqueue 1, :run_at => Time.now + 60
72
- DB[:que_jobs].count.should be 1
73
-
74
- job = DB[:que_jobs].first
75
- job[:queue].should == ''
76
- job[:priority].should be 100
77
- job[:run_at].should be_within(3).of Time.now + 60
78
- job[:job_class].should == "Que::Job"
79
- JSON.load(job[:args]).should == [1]
80
- end
81
-
82
- it "should be able to queue a job with a specific priority" do
83
- DB[:que_jobs].count.should be 0
84
- Que::Job.enqueue 1, :priority => 4
85
- DB[:que_jobs].count.should be 1
86
-
87
- job = DB[:que_jobs].first
88
- job[:queue].should == ''
89
- job[:priority].should be 4
90
- job[:run_at].should be_within(3).of Time.now
91
- job[:job_class].should == "Que::Job"
92
- JSON.load(job[:args]).should == [1]
93
- end
94
-
95
- it "should be able to queue a job with queueing options in addition to argument options" do
96
- DB[:que_jobs].count.should be 0
97
- Que::Job.enqueue 1, :string => "string", :run_at => Time.now + 60, :priority => 4
98
- DB[:que_jobs].count.should be 1
99
-
100
- job = DB[:que_jobs].first
101
- job[:queue].should == ''
102
- job[:priority].should be 4
103
- job[:run_at].should be_within(3).of Time.now + 60
104
- job[:job_class].should == "Que::Job"
105
- JSON.load(job[:args]).should == [1, {'string' => 'string'}]
106
- end
107
-
108
- it "should respect a job class defined as a string" do
109
- Que.enqueue 'argument', :queue => 'my_queue', :other_arg => 'other_arg', :job_class => 'MyJobClass'
110
- Que::Job.enqueue 'argument', :queue => 'my_queue', :other_arg => 'other_arg', :job_class => 'MyJobClass'
111
-
112
- DB[:que_jobs].count.should be 2
113
- DB[:que_jobs].all.each do |job|
114
- job[:job_class].should == 'MyJobClass'
115
- job[:queue].should == 'my_queue'
116
- JSON.load(job[:args]).should == ['argument', {'other_arg' => 'other_arg'}]
117
- end
118
- end
119
-
120
- it "should respect a default (but overridable) priority for the job class" do
121
- class DefaultPriorityJob < Que::Job
122
- @priority = 3
123
- end
124
-
125
- DB[:que_jobs].count.should be 0
126
- DefaultPriorityJob.enqueue 1
127
- DefaultPriorityJob.enqueue 1, :priority => 4
128
- DB[:que_jobs].count.should be 2
129
-
130
- first, second = DB[:que_jobs].order(:job_id).all
131
-
132
- first[:queue].should == ''
133
- first[:priority].should be 3
134
- first[:run_at].should be_within(3).of Time.now
135
- first[:job_class].should == "DefaultPriorityJob"
136
- JSON.load(first[:args]).should == [1]
137
-
138
- second[:queue].should == ''
139
- second[:priority].should be 4
140
- second[:run_at].should be_within(3).of Time.now
141
- second[:job_class].should == "DefaultPriorityJob"
142
- JSON.load(second[:args]).should == [1]
143
- end
144
-
145
- it "should respect the old @default_priority setting" do
146
- class OldDefaultPriorityJob < Que::Job
147
- @default_priority = 3
148
- end
149
-
150
- DB[:que_jobs].count.should be 0
151
- suppress_warnings do
152
- OldDefaultPriorityJob.enqueue 1
153
- OldDefaultPriorityJob.enqueue 1, :priority => 4
154
- end
155
- DB[:que_jobs].count.should be 2
156
-
157
- first, second = DB[:que_jobs].order(:job_id).all
158
-
159
- first[:queue].should == ''
160
- first[:priority].should be 3
161
- first[:run_at].should be_within(3).of Time.now
162
- first[:job_class].should == "OldDefaultPriorityJob"
163
- JSON.load(first[:args]).should == [1]
164
-
165
- second[:queue].should == ''
166
- second[:priority].should be 4
167
- second[:run_at].should be_within(3).of Time.now
168
- second[:job_class].should == "OldDefaultPriorityJob"
169
- JSON.load(second[:args]).should == [1]
170
- end
171
-
172
- it "should respect a default (but overridable) run_at for the job class" do
173
- class DefaultRunAtJob < Que::Job
174
- @run_at = -> { Time.now + 60 }
175
- end
176
-
177
- DB[:que_jobs].count.should be 0
178
- DefaultRunAtJob.enqueue 1
179
- DefaultRunAtJob.enqueue 1, :run_at => Time.now + 30
180
- DB[:que_jobs].count.should be 2
181
-
182
- first, second = DB[:que_jobs].order(:job_id).all
183
-
184
- first[:queue].should == ''
185
- first[:priority].should be 100
186
- first[:run_at].should be_within(3).of Time.now + 60
187
- first[:job_class].should == "DefaultRunAtJob"
188
- JSON.load(first[:args]).should == [1]
189
-
190
- second[:queue].should == ''
191
- second[:priority].should be 100
192
- second[:run_at].should be_within(3).of Time.now + 30
193
- second[:job_class].should == "DefaultRunAtJob"
194
- JSON.load(second[:args]).should == [1]
195
- end
196
-
197
- it "should respect the old @default_run_at setting" do
198
- class OldDefaultRunAtJob < Que::Job
199
- @default_run_at = -> { Time.now + 60 }
200
- end
201
-
202
- DB[:que_jobs].count.should be 0
203
- suppress_warnings do
204
- OldDefaultRunAtJob.enqueue 1
205
- OldDefaultRunAtJob.enqueue 1, :run_at => Time.now + 30
206
- end
207
- DB[:que_jobs].count.should be 2
208
-
209
- first, second = DB[:que_jobs].order(:job_id).all
210
-
211
- first[:queue].should == ''
212
- first[:priority].should be 100
213
- first[:run_at].should be_within(3).of Time.now + 60
214
- first[:job_class].should == "OldDefaultRunAtJob"
215
- JSON.load(first[:args]).should == [1]
216
-
217
- second[:queue].should == ''
218
- second[:priority].should be 100
219
- second[:run_at].should be_within(3).of Time.now + 30
220
- second[:job_class].should == "OldDefaultRunAtJob"
221
- JSON.load(second[:args]).should == [1]
222
- end
223
-
224
- it "should respect a default (but overridable) queue for the job class" do
225
- class NamedQueueJob < Que::Job
226
- @queue = :my_queue
227
- end
228
-
229
- DB[:que_jobs].count.should be 0
230
- NamedQueueJob.enqueue 1
231
- NamedQueueJob.enqueue 1, :queue => 'my_queue_2'
232
- NamedQueueJob.enqueue 1, :queue => :my_queue_2
233
- NamedQueueJob.enqueue 1, :queue => ''
234
- NamedQueueJob.enqueue 1, :queue => nil
235
- DB[:que_jobs].count.should be 5
236
-
237
- first, second, third, fourth, fifth = DB[:que_jobs].order(:job_id).select_map(:queue)
238
-
239
- first.should == 'my_queue'
240
- second.should == 'my_queue_2'
241
- third.should == 'my_queue_2'
242
- fourth.should == ''
243
- fifth.should == ''
244
- end
245
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Que, 'helpers' do
6
- it "should be able to clear the jobs table" do
7
- DB[:que_jobs].insert :job_class => "Que::Job"
8
- DB[:que_jobs].count.should be 1
9
- Que.clear!
10
- DB[:que_jobs].count.should be 0
11
- end
12
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe "Logging" do
6
- it "by default should record the library and hostname and thread id in JSON" do
7
- Que.log :event => "blah", :source => 4
8
- $logger.messages.count.should be 1
9
-
10
- message = JSON.load($logger.messages.first)
11
- message['lib'].should == 'que'
12
- message['hostname'].should == Socket.gethostname
13
- message['pid'].should == Process.pid
14
- message['event'].should == 'blah'
15
- message['source'].should == 4
16
- message['thread'].should == Thread.current.object_id
17
- end
18
-
19
- it "should allow a callable to be set as the logger" do
20
- begin
21
- # Make sure we can get through a work cycle without a logger.
22
- Que.logger = proc { $logger }
23
-
24
- Que::Job.enqueue
25
- worker = Que::Worker.new
26
- sleep_until { worker.sleeping? }
27
-
28
- DB[:que_jobs].should be_empty
29
-
30
- worker.stop
31
- worker.wait_until_stopped
32
-
33
- $logger.messages.count.should be 2
34
- $logger.messages.map{|m| JSON.load(m)['event']}.should == ['job_worked', 'job_unavailable']
35
- ensure
36
- Que.logger = $logger
37
- end
38
- end
39
-
40
- it "should not raise an error when no logger is present" do
41
- begin
42
- # Make sure we can get through a work cycle without a logger.
43
- Que.logger = nil
44
-
45
- Que::Job.enqueue
46
- worker = Que::Worker.new
47
- sleep_until { worker.sleeping? }
48
-
49
- DB[:que_jobs].should be_empty
50
-
51
- worker.stop
52
- worker.wait_until_stopped
53
- ensure
54
- Que.logger = $logger
55
- end
56
- end
57
-
58
- it "should allow the use of a custom log formatter" do
59
- begin
60
- Que.log_formatter = proc { |data| "Logged event is #{data[:event]}" }
61
- Que.log :event => 'my_event'
62
- $logger.messages.count.should be 1
63
- $logger.messages.first.should == "Logged event is my_event"
64
- ensure
65
- Que.log_formatter = nil
66
- end
67
- end
68
-
69
- it "should not log anything if the logging formatter returns falsey" do
70
- begin
71
- Que.log_formatter = proc { |data| false }
72
-
73
- Que.log :event => "blah"
74
- $logger.messages.should be_empty
75
- ensure
76
- Que.log_formatter = nil
77
- end
78
- end
79
-
80
- it "should use a :level option to set the log level if one exists, or default to info" do
81
- begin
82
- Que.logger = o = Object.new
83
-
84
- def o.method_missing(level, message)
85
- $level = level
86
- $message = message
87
- end
88
-
89
- Que.log :message => 'one'
90
- $level.should == :info
91
- JSON.load($message)['message'].should == 'one'
92
-
93
- Que.log :message => 'two', :level => 'debug'
94
- $level.should == :debug
95
- JSON.load($message)['message'].should == 'two'
96
- ensure
97
- Que.logger = $logger
98
- $level = $message = nil
99
- end
100
- end
101
- end