jiggler 0.1.0.rc4 → 0.1.0.rc5

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -200
  3. data/bin/jiggler +1 -1
  4. data/lib/jiggler/at_least_once/acknowledger.rb +43 -0
  5. data/lib/jiggler/at_least_once/fetcher.rb +93 -0
  6. data/lib/jiggler/at_most_once/acknowledger.rb +21 -0
  7. data/lib/jiggler/at_most_once/fetcher.rb +46 -0
  8. data/lib/jiggler/base_acknowledger.rb +11 -0
  9. data/lib/jiggler/base_fetcher.rb +14 -0
  10. data/lib/jiggler/cleaner.rb +14 -5
  11. data/lib/jiggler/cli.rb +3 -2
  12. data/lib/jiggler/config.rb +48 -4
  13. data/lib/jiggler/launcher.rb +9 -3
  14. data/lib/jiggler/manager.rb +26 -2
  15. data/lib/jiggler/retrier.rb +8 -10
  16. data/lib/jiggler/scheduled/enqueuer.rb +1 -1
  17. data/lib/jiggler/scheduled/poller.rb +38 -26
  18. data/lib/jiggler/scheduled/requeuer.rb +57 -0
  19. data/lib/jiggler/server.rb +7 -0
  20. data/lib/jiggler/stats/collection.rb +3 -2
  21. data/lib/jiggler/stats/monitor.rb +2 -2
  22. data/lib/jiggler/summary.rb +8 -1
  23. data/lib/jiggler/support/helper.rb +17 -3
  24. data/lib/jiggler/version.rb +1 -1
  25. data/lib/jiggler/web.rb +0 -2
  26. data/lib/jiggler/worker.rb +21 -36
  27. data/spec/examples.txt +96 -79
  28. data/spec/fixtures/config/jiggler.yml +2 -2
  29. data/spec/jiggler/at_least_once/acknowledger_spec.rb +30 -0
  30. data/spec/jiggler/at_least_once/fetcher_spec.rb +69 -0
  31. data/spec/jiggler/at_most_once/fetcher_spec.rb +33 -0
  32. data/spec/jiggler/cleaner_spec.rb +11 -1
  33. data/spec/jiggler/cli_spec.rb +5 -7
  34. data/spec/jiggler/config_spec.rb +45 -3
  35. data/spec/jiggler/core_spec.rb +2 -0
  36. data/spec/jiggler/job_spec.rb +4 -4
  37. data/spec/jiggler/launcher_spec.rb +60 -54
  38. data/spec/jiggler/manager_spec.rb +50 -41
  39. data/spec/jiggler/retrier_spec.rb +3 -1
  40. data/spec/jiggler/scheduled/requeuer_spec.rb +57 -0
  41. data/spec/jiggler/stats/monitor_spec.rb +3 -2
  42. data/spec/jiggler/summary_spec.rb +19 -5
  43. data/spec/jiggler/worker_spec.rb +11 -15
  44. data/spec/spec_helper.rb +7 -0
  45. metadata +18 -3
@@ -1,52 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Jiggler::Manager do
4
- let(:config) do
5
- Jiggler::Config.new(
6
- concurrency: 4,
7
- timeout: 1,
8
- server_mode: true
9
- )
10
- end
11
- let(:collection) { Jiggler::Stats::Collection.new(config) }
12
- let(:manager) { described_class.new(config, collection) }
4
+ let(:uuid) { "#{SecureRandom.hex(3)}-test" }
5
+ let(:collection) { Jiggler::Stats::Collection.new(uuid, uuid) }
13
6
 
14
- it { expect(manager.instance_variable_get(:@workers).count).to be 4 }
7
+ [:at_most_once, :at_least_once].each do |mode|
8
+ context "with #{mode} mode" do
9
+ let(:config) do
10
+ Jiggler::Config.new(
11
+ concurrency: 4,
12
+ timeout: 1,
13
+ mode: mode
14
+ )
15
+ end
16
+ let(:manager) { described_class.new(config, collection) }
15
17
 
16
- describe '#start' do
17
- it 'starts the manager' do
18
- expect(manager.instance_variable_get(:@workers)).to all(receive(:run))
19
- Async { manager.start }
20
- sleep(0.5)
21
- manager.terminate
22
- end
23
- end
18
+ it { expect(manager.instance_variable_get(:@workers).count).to be 4 }
24
19
 
25
- describe '#suspend' do
26
- it 'suspends the manager' do
27
- expect(manager.instance_variable_get(:@workers)).to all(receive(:suspend).and_call_original)
28
- task = Async do
29
- Async { manager.start }
30
- sleep(0.5)
31
- manager.suspend
32
- expect(manager.instance_variable_get(:@done)).to be true
20
+ describe '#start' do
21
+ it 'starts the manager' do
22
+ expect(manager.instance_variable_get(:@workers)).to all(receive(:run))
23
+ task = Async do
24
+ Async { manager.start }
25
+ sleep(0.5)
26
+ manager.terminate
27
+ end
28
+ task.wait
29
+ end
33
30
  end
34
- task.wait
35
- end
36
- end
37
-
38
- describe '#terminate' do
39
- it 'terminates the manager' do
40
- expect(manager.instance_variable_get(:@workers)).to all(receive(:suspend).and_call_original)
41
- expect(manager.instance_variable_get(:@workers)).to all(receive(:terminate).and_call_original)
42
- task = Async do
43
- Async { manager.start }
44
- sleep(0.5)
45
- manager.terminate
46
- sleep(2) # wait for timeout
47
- expect(manager.instance_variable_get(:@done)).to be true
31
+
32
+ describe '#suspend' do
33
+ it 'suspends the manager' do
34
+ expect(manager.instance_variable_get(:@fetcher)).to receive(:suspend).and_call_original
35
+ task = Async do
36
+ Async { manager.start }
37
+ sleep(0.5)
38
+ manager.suspend
39
+ expect(manager.instance_variable_get(:@done)).to be true
40
+ manager.terminate
41
+ end
42
+ task.wait
43
+ end
44
+ end
45
+
46
+ describe '#terminate' do
47
+ it 'terminates the manager' do
48
+ expect(manager.instance_variable_get(:@fetcher)).to receive(:suspend).and_call_original
49
+ task = Async do
50
+ Async { manager.start }
51
+ sleep(0.5)
52
+ manager.terminate
53
+ sleep(2) # wait for timeout
54
+ expect(manager.instance_variable_get(:@done)).to be true
55
+ end
56
+ task.wait
57
+ end
48
58
  end
49
- task.wait
50
59
  end
51
60
  end
52
61
  end
@@ -8,7 +8,9 @@ RSpec.describe Jiggler::Retrier do
8
8
  queues: ['test']
9
9
  )
10
10
  end
11
- let(:collection) { Jiggler::Stats::Collection.new('test-retrier-uuid') }
11
+ let(:uuid) { "#{SecureRandom.hex(3)}-test" }
12
+ let(:identity) { "#{uuid}-identity" }
13
+ let(:collection) { Jiggler::Stats::Collection.new(uuid, identity) }
12
14
  let(:retrier) { Jiggler::Retrier.new(config, collection) }
13
15
 
14
16
  describe '#wrapped' do
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Jiggler::Scheduled::Requeuer do
4
+ let(:config) do
5
+ Jiggler::Config.new(
6
+ concurrency: 1,
7
+ timeout: 1,
8
+ poller_enabled: false,
9
+ queues: ['my_queue']
10
+ )
11
+ end
12
+ let(:launcher) { Jiggler::Launcher.new(config) }
13
+ let(:identity) { launcher.send(:identity) }
14
+ let(:uuid) { launcher.send(:uuid) }
15
+ let(:requeuer) { Jiggler::Scheduled::Requeuer.new(config) }
16
+
17
+ after { config.cleaner.prune_all }
18
+
19
+ describe '#running_processes_uuid' do
20
+ it 'fetches process uuids' do
21
+ config.with_sync_redis do |conn|
22
+ conn.call('SET', identity, 'test')
23
+ end
24
+ expect(requeuer.send(:running_processes_uuid)).to eq([uuid])
25
+ end
26
+ end
27
+
28
+ describe '#requeue_data' do
29
+ it 'selects data without running processes' do
30
+ config.with_sync_redis do |conn|
31
+ conn.call('SET', identity, 'test')
32
+ conn.call('LPUSH', "jiggler:list:my_queue:in_progress:#{uuid}", 'test')
33
+ end
34
+ expect(requeuer.send(:requeue_data)).to eq([])
35
+ config.with_sync_redis do |conn|
36
+ conn.call('DEL', identity)
37
+ end
38
+ expect(requeuer.send(:requeue_data)).to eq([
39
+ ["jiggler:list:my_queue:in_progress:#{uuid}", "jiggler:list:my_queue", uuid]
40
+ ])
41
+ end
42
+ end
43
+
44
+ describe '#handle_stale' do
45
+ it 'requeues stale data' do
46
+ config.with_sync_redis do |conn|
47
+ conn.call('LPUSH', "jiggler:list:my_queue:in_progress:#{uuid}", 'test')
48
+ expect(conn.call('LLEN', 'jiggler:list:my_queue')).to be 0
49
+ end
50
+ requeuer.handle_stale
51
+ config.with_sync_redis do |conn|
52
+ expect(conn.call('LLEN', "jiggler:list:my_queue:in_progress:#{uuid}")).to be 0
53
+ expect(conn.call('LLEN', 'jiggler:list:my_queue')).to be 1
54
+ end
55
+ end
56
+ end
57
+ end
@@ -8,7 +8,8 @@ RSpec.describe Jiggler::Stats::Monitor do
8
8
  )
9
9
  end
10
10
  let(:uuid) { 'monitor-test-uuid' }
11
- let(:collection) { Jiggler::Stats::Collection.new(uuid) }
11
+ let(:identity) { "#{uuid}-identity" }
12
+ let(:collection) { Jiggler::Stats::Collection.new(uuid, identity) }
12
13
  let(:monitor) { described_class.new(config, collection) }
13
14
 
14
15
  describe '#start' do
@@ -32,7 +33,7 @@ RSpec.describe Jiggler::Stats::Monitor do
32
33
  expect(monitor).to receive(:cleanup).and_call_original
33
34
  monitor.terminate
34
35
  expect(monitor.instance_variable_get(:@done)).to be true
35
- expect(config.client_redis_pool.acquire { |conn| conn.call('GET', uuid) }).to be nil
36
+ expect(config.client_redis_pool.acquire { |conn| conn.call('GET', identity) }).to be nil
36
37
  end
37
38
  task.wait
38
39
  end
@@ -8,10 +8,14 @@ RSpec.describe Jiggler::Summary do
8
8
  timeout: 1,
9
9
  stats_interval: 1,
10
10
  queues: queues,
11
- poller_enabled: false
11
+ poller_enabled: false,
12
+ mode: :at_most_once
12
13
  )
13
14
  end
14
- let(:collection) { Jiggler::Stats::Collection.new('summary-test-uuid') }
15
+ let(:uuid) { "#{SecureRandom.hex(3)}-test" }
16
+ let(:collection) { Jiggler::Stats::Collection.new(uuid, uuid) }
17
+ let(:acknowledger) { Jiggler::AtMostOnce::Acknowledger.new(config) }
18
+ let(:fetcher) { Jiggler::AtMostOnce::Fetcher.new(config, collection) }
15
19
  let(:summary) { described_class.new(config) }
16
20
 
17
21
  describe '.all' do
@@ -33,7 +37,7 @@ RSpec.describe Jiggler::Summary do
33
37
  Sync do
34
38
  config.cleaner.prune_all
35
39
  launcher = Jiggler::Launcher.new(config)
36
- uuid = launcher.send(:uuid)
40
+ uuid = launcher.send(:identity)
37
41
  MyJob.with_options(queue: 'queue1').enqueue
38
42
 
39
43
  first_summary = summary.all
@@ -90,12 +94,13 @@ RSpec.describe Jiggler::Summary do
90
94
 
91
95
  describe '#last_dead_jobs' do
92
96
  it 'returns last n dead jobs' do
97
+ # clean data and enqueue a failling job with no retries
93
98
  Sync do
94
99
  config.cleaner.prune_all
95
100
  expect(summary.last_dead_jobs(1)).to be_empty
96
101
  MyFailedJob.with_options(queue: 'queue1', retries: 0).enqueue('yay')
97
102
  end
98
- worker = Jiggler::Worker.new(config, collection) do
103
+ worker = Jiggler::Worker.new(config, collection, acknowledger, fetcher) do
99
104
  config.logger.info('Doing some weird dead testings')
100
105
  end
101
106
  task = Async do
@@ -106,6 +111,8 @@ RSpec.describe Jiggler::Summary do
106
111
  worker.terminate
107
112
  end
108
113
  task.wait
114
+
115
+ # ensure the job is saved as dead
109
116
  jobs = Sync { summary.last_dead_jobs(3) }
110
117
  expect(jobs.count).to be 1
111
118
  expect(jobs.first).to include({
@@ -117,6 +124,7 @@ RSpec.describe Jiggler::Summary do
117
124
 
118
125
  describe '#last_retry_jobs' do
119
126
  it 'returns last n retry jobs' do
127
+ # clean data and enqueue 5 failling jobs
120
128
  Sync do
121
129
  config.cleaner.prune_all
122
130
  expect(summary.last_retry_jobs(3)).to be_empty
@@ -127,9 +135,12 @@ RSpec.describe Jiggler::Summary do
127
135
  ).enqueue("yay-#{i}")
128
136
  end
129
137
  end
130
- worker = Jiggler::Worker.new(config, collection) do
138
+
139
+ worker = Jiggler::Worker.new(config, collection, acknowledger, fetcher) do
131
140
  config.logger.info('Doing some weird retry testings')
132
141
  end
142
+
143
+ # start worker, wait for 1 sec, terminate worker
133
144
  task = Async do
134
145
  Async do
135
146
  worker.run
@@ -138,7 +149,10 @@ RSpec.describe Jiggler::Summary do
138
149
  worker.terminate
139
150
  end
140
151
  task.wait
152
+
153
+ # fetch last 3 retry jobs to ensure they are in the right order
141
154
  jobs = Sync { summary.last_retry_jobs(3) }
155
+ puts jobs.first
142
156
  expect(jobs.count).to be 3
143
157
  expect(jobs.first).to include({
144
158
  'name' => 'MyFailedJob',
@@ -1,22 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Jiggler::Worker do
4
- before(:all) do
4
+ before(:all) do
5
5
  Jiggler.instance_variable_set(:@config, Jiggler::Config.new(
6
6
  concurrency: 1,
7
7
  client_concurrency: 1,
8
8
  timeout: 1,
9
- queues: ['default', 'test']
10
- ) )
9
+ queues: [['default', 2], ['test', 1]],
10
+ mode: :at_most_once
11
+ ))
11
12
  end
12
13
  after(:all) do
13
14
  Jiggler.instance_variable_set(:@config, Jiggler::Config.new)
14
15
  end
15
16
 
16
17
  let(:config) { Jiggler.config }
17
- let(:collection) { Jiggler::Stats::Collection.new(config) }
18
+ let(:uuid) { "#{SecureRandom.hex(3)}-test" }
19
+ let(:collection) { Jiggler::Stats::Collection.new(uuid, uuid) }
20
+ let(:acknowledger) { Jiggler::AtMostOnce::Acknowledger.new(config) }
21
+ let(:fetcher) { Jiggler::AtMostOnce::Fetcher.new(config, collection) }
18
22
  let(:worker) do
19
- described_class.new(config, collection) do
23
+ described_class.new(config, collection, acknowledger, fetcher) do
20
24
  config.logger.debug("Callback called: #{rand(100)}")
21
25
  end
22
26
  end
@@ -90,20 +94,12 @@ RSpec.describe Jiggler::Worker do
90
94
  context 'when worker is running' do
91
95
  it 'terminates the worker' do
92
96
  task = Async do
93
- expect(worker.done).to be false
94
97
  Async { worker.run }
98
+ sleep(0.5)
95
99
  worker.terminate
96
100
  end
97
101
  task.wait
98
- expect(worker.done).to be true
99
- end
100
- end
101
-
102
- context 'when worker is not running' do
103
- it do
104
- expect(worker.done).to be false
105
- worker.terminate
106
- expect(worker.done).to be true
102
+ expect(worker.instance_variable_get(:@runner)).to be_nil
107
103
  end
108
104
  end
109
105
  end
data/spec/spec_helper.rb CHANGED
@@ -10,12 +10,19 @@ require 'jiggler/web'
10
10
  require 'jiggler/support/helper'
11
11
  require 'jiggler/scheduled/enqueuer'
12
12
  require 'jiggler/scheduled/poller'
13
+ require 'jiggler/scheduled/requeuer'
13
14
  require 'jiggler/stats/collection'
14
15
  require 'jiggler/stats/monitor'
15
16
  require 'jiggler/errors'
16
17
  require 'jiggler/retrier'
17
18
  require 'jiggler/launcher'
18
19
  require 'jiggler/manager'
20
+ require 'jiggler/base_acknowledger'
21
+ require 'jiggler/base_fetcher'
22
+ require 'jiggler/at_most_once/acknowledger'
23
+ require 'jiggler/at_most_once/fetcher'
24
+ require 'jiggler/at_least_once/acknowledger'
25
+ require 'jiggler/at_least_once/fetcher'
19
26
  require 'jiggler/worker'
20
27
  require 'jiggler/cli'
21
28
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jiggler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.rc4
4
+ version: 0.1.0.rc5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julija Alieckaja
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-01-18 00:00:00.000000000 Z
12
+ date: 2023-02-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: async
@@ -135,7 +135,13 @@ files:
135
135
  - README.md
136
136
  - bin/jiggler
137
137
  - lib/jiggler.rb
138
+ - lib/jiggler/at_least_once/acknowledger.rb
139
+ - lib/jiggler/at_least_once/fetcher.rb
140
+ - lib/jiggler/at_most_once/acknowledger.rb
141
+ - lib/jiggler/at_most_once/fetcher.rb
138
142
  - lib/jiggler/base.rb
143
+ - lib/jiggler/base_acknowledger.rb
144
+ - lib/jiggler/base_fetcher.rb
139
145
  - lib/jiggler/cleaner.rb
140
146
  - lib/jiggler/cli.rb
141
147
  - lib/jiggler/client.rb
@@ -149,6 +155,7 @@ files:
149
155
  - lib/jiggler/retrier.rb
150
156
  - lib/jiggler/scheduled/enqueuer.rb
151
157
  - lib/jiggler/scheduled/poller.rb
158
+ - lib/jiggler/scheduled/requeuer.rb
152
159
  - lib/jiggler/server.rb
153
160
  - lib/jiggler/stats/collection.rb
154
161
  - lib/jiggler/stats/monitor.rb
@@ -165,6 +172,9 @@ files:
165
172
  - spec/fixtures/my_failed_job.rb
166
173
  - spec/fixtures/my_job.rb
167
174
  - spec/fixtures/my_job_with_args.rb
175
+ - spec/jiggler/at_least_once/acknowledger_spec.rb
176
+ - spec/jiggler/at_least_once/fetcher_spec.rb
177
+ - spec/jiggler/at_most_once/fetcher_spec.rb
168
178
  - spec/jiggler/cleaner_spec.rb
169
179
  - spec/jiggler/cli_spec.rb
170
180
  - spec/jiggler/config_spec.rb
@@ -176,6 +186,7 @@ files:
176
186
  - spec/jiggler/retrier_spec.rb
177
187
  - spec/jiggler/scheduled/enqueuer_spec.rb
178
188
  - spec/jiggler/scheduled/poller_spec.rb
189
+ - spec/jiggler/scheduled/requeuer_spec.rb
179
190
  - spec/jiggler/stats/monitor_spec.rb
180
191
  - spec/jiggler/summary_spec.rb
181
192
  - spec/jiggler/web_spec.rb
@@ -204,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
215
  - !ruby/object:Gem::Version
205
216
  version: 1.3.1
206
217
  requirements: []
207
- rubygems_version: 3.4.3
218
+ rubygems_version: 3.4.6
208
219
  signing_key:
209
220
  specification_version: 4
210
221
  summary: Ruby background job processor
@@ -215,6 +226,9 @@ test_files:
215
226
  - spec/fixtures/my_failed_job.rb
216
227
  - spec/fixtures/my_job.rb
217
228
  - spec/fixtures/my_job_with_args.rb
229
+ - spec/jiggler/at_least_once/acknowledger_spec.rb
230
+ - spec/jiggler/at_least_once/fetcher_spec.rb
231
+ - spec/jiggler/at_most_once/fetcher_spec.rb
218
232
  - spec/jiggler/cleaner_spec.rb
219
233
  - spec/jiggler/cli_spec.rb
220
234
  - spec/jiggler/config_spec.rb
@@ -226,6 +240,7 @@ test_files:
226
240
  - spec/jiggler/retrier_spec.rb
227
241
  - spec/jiggler/scheduled/enqueuer_spec.rb
228
242
  - spec/jiggler/scheduled/poller_spec.rb
243
+ - spec/jiggler/scheduled/requeuer_spec.rb
229
244
  - spec/jiggler/stats/monitor_spec.rb
230
245
  - spec/jiggler/summary_spec.rb
231
246
  - spec/jiggler/web_spec.rb