sidekiq-fairplay 0.0.1 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8da6198834317f72485926227a1a0798f26fa2cb89506248b8430f36445c3d8e
4
- data.tar.gz: 1b09fd7ff17a68822a77d2944a22f9913a3048660e591aebb0fcdcf71ef69b8f
3
+ metadata.gz: 73751d48396c6e9c645bcea222fa2d2ff431cd3b975030be8eeefdcfe19f2e98
4
+ data.tar.gz: f7b0d50c472dd079d294c93537451b95d47a7a654298be25a064a9e7d013e708
5
5
  SHA512:
6
- metadata.gz: 74bfa63effdd8815a733acb146f7acd5bfa6203eef103c22ba79f1b170fc3de9085b52cd6086b37d86d32d7da2110af2896e8ce562f191648c47c6e924b33292
7
- data.tar.gz: f06564822787aa2e4c01072a450f12dc7ba78539457bef069ed6c38708d8989bf03b1881b4bd9a26e3e0ae2ffa3002bf455bcc959b403424cafc019728be98fb
6
+ metadata.gz: e2dcf5b7184846e368ceae0bd76b0805dc469458411018e3c85b8be1eaa619e4921e7f16bf004986b01451886cf43ff0309cda2b3327205d0b9b79bc082b356a
7
+ data.tar.gz: da24fd2f95cf95d8b7997cf627a82d5a9c456373894ec58eb91c633af0aadf337d54187512eabcbac527c658df8f2cdd25df5b329cc7f2d1eba45edc59ca3683
data/README.md CHANGED
@@ -62,17 +62,20 @@ Configure the client middleware on both client and server:
62
62
  ```ruby
63
63
  Sidekiq.configure_client do |config|
64
64
  config.client_middleware do |chain|
65
- chain.add Sidekiq::Fairplay::Middleware
65
+ chain.prepend Sidekiq::Fairplay::Middleware
66
66
  end
67
67
  end
68
68
 
69
69
  Sidekiq.configure_server do |config|
70
70
  config.client_middleware do |chain|
71
- chain.add Sidekiq::Fairplay::Middleware
71
+ chain.prepend Sidekiq::Fairplay::Middleware
72
72
  end
73
73
  end
74
74
  ```
75
75
 
76
+ > [!TIP]
77
+ > It's best to insert the middleware at the start of the chain using the [`#prepend` method](https://github.com/sidekiq/sidekiq/blob/d6395641571eba33050d34526bf93bed92504d4d/lib/sidekiq/middleware/chain.rb#L125), as shown above. This is important because `Sidekiq::Fairplay::Middleware` runs twice: first when you attempt to enqueue the job and it gets intercepted, and again when the planner actually enqueues it. If other middlewares are placed before it, this double execution can cause subtle issues. For example, if you use `unique_for`, you must ensure that `Sidekiq::Fairplay::Middleware` comes before `Sidekiq::Enterprise::Unique::Client`; otherwise, such jobs may lock themselves out of execution.
78
+
76
79
  ## API
77
80
 
78
81
  In the following example you can see all of the available configuration parameters and their meaning:
@@ -171,8 +174,8 @@ We use two simple Redis-backed distributed locks:
171
174
  - Ensures only one planner per job class runs at a time.
172
175
  - Not strictly necessary (the first lock already prevents most issues), but adds safety.
173
176
 
174
- ⚠️ Note: If a planner takes longer than its `planner_lock_ttl`, multiple planners may run concurrently.
175
- It's not the end of the world, but it means you probably should **optimize your `tenant_weights` logic** and/or increase the `enqueue_interval`.
177
+ > [!WARNING]
178
+ > If a planner takes longer than its `planner_lock_ttl`, multiple planners may run concurrently. It's not the end of the world, but it means you probably should **optimize your `tenant_weights` logic** and/or increase the `enqueue_interval`.
176
179
 
177
180
  ## Troubleshooting
178
181
 
@@ -1,5 +1,5 @@
1
1
  module Sidekiq
2
2
  module Fairplay
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-fairplay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Baygeldin
@@ -153,58 +153,44 @@ dependencies:
153
153
  name: activesupport
154
154
  requirement: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - "~>"
156
+ - - ">="
157
157
  - !ruby/object:Gem::Version
158
158
  version: '7.0'
159
159
  type: :runtime
160
160
  prerelease: false
161
161
  version_requirements: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - "~>"
163
+ - - ">="
164
164
  - !ruby/object:Gem::Version
165
165
  version: '7.0'
166
166
  - !ruby/object:Gem::Dependency
167
167
  name: sidekiq
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - "~>"
170
+ - - ">="
171
171
  - !ruby/object:Gem::Version
172
172
  version: '7.0'
173
173
  type: :runtime
174
174
  prerelease: false
175
175
  version_requirements: !ruby/object:Gem::Requirement
176
176
  requirements:
177
- - - "~>"
177
+ - - ">="
178
178
  - !ruby/object:Gem::Version
179
179
  version: '7.0'
180
180
  email:
181
181
  - a.baygeldin@gmail.com
182
- executables:
183
- - console
184
- - setup
182
+ executables: []
185
183
  extensions: []
186
184
  extra_rdoc_files: []
187
185
  files:
188
- - ".github/workflows/ci.yml"
189
- - ".gitignore"
190
- - ".standard.yml"
191
- - Gemfile
192
186
  - LICENSE
193
187
  - README.md
194
- - Rakefile
195
- - bin/console
196
- - bin/setup
197
- - gemfiles/sidekiq_7.gemfile
198
- - gemfiles/sidekiq_8.gemfile
199
188
  - lib/sidekiq/fairplay.rb
200
189
  - lib/sidekiq/fairplay/config.rb
201
190
  - lib/sidekiq/fairplay/middleware.rb
202
191
  - lib/sidekiq/fairplay/planner.rb
203
192
  - lib/sidekiq/fairplay/redis.rb
204
193
  - lib/sidekiq/fairplay/version.rb
205
- - sidekiq-fairplay.gemspec
206
- - spec/sidekiq/fairplay_spec.rb
207
- - spec/spec_helper.rb
208
194
  homepage: http://github.com/baygeldin/sidekiq-fairplay
209
195
  licenses:
210
196
  - MIT
@@ -1,76 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [ main, master ]
6
- pull_request:
7
- branches: [ main, master ]
8
-
9
- jobs:
10
- test:
11
- name: Test (Ruby ${{ matrix.ruby }}, Sidekiq ${{ matrix.sidekiq }})
12
- runs-on: ubuntu-latest
13
- timeout-minutes: 15
14
- strategy:
15
- fail-fast: false
16
- matrix:
17
- ruby: ['3.4']
18
- sidekiq: ['7', '8']
19
-
20
- services:
21
- redis:
22
- image: redis:7-alpine
23
- ports:
24
- - 6379:6379
25
- options: >-
26
- --health-cmd "redis-cli ping || exit 1"
27
- --health-interval 10s
28
- --health-timeout 5s
29
- --health-retries 5
30
-
31
- steps:
32
- - name: Checkout
33
- uses: actions/checkout@v4
34
-
35
- - name: Set up Ruby
36
- uses: ruby/setup-ruby@v1
37
- with:
38
- ruby-version: ${{ matrix.ruby }}
39
- bundler-cache: true
40
-
41
- - name: Select Gemfile for Sidekiq ${{ matrix.sidekiq }}
42
- run: |
43
- export BUNDLE_GEMFILE="gemfiles/sidekiq_${{ matrix.sidekiq }}.gemfile"
44
- echo "BUNDLE_GEMFILE=$BUNDLE_GEMFILE" >> $GITHUB_ENV
45
-
46
- - name: Bundle install
47
- run: bundle install --jobs 4 --retry 3
48
-
49
- - name: Run specs
50
- env:
51
- REDIS_URL: redis://localhost:6379/1
52
- run: |
53
- bundle exec rspec --format progress
54
-
55
- - uses: qltysh/qlty-action/coverage@v2
56
- if: matrix.sidekiq == '8' && matrix.ruby == '3.4'
57
- with:
58
- token: ${{secrets.QLTY_COVERAGE_TOKEN}}
59
- files: coverage/.resultset.json
60
-
61
- lint:
62
- name: Lint (standardrb)
63
- runs-on: ubuntu-latest
64
- continue-on-error: true
65
- steps:
66
- - name: Checkout
67
- uses: actions/checkout@v4
68
-
69
- - name: Set up Ruby
70
- uses: ruby/setup-ruby@v1
71
- with:
72
- ruby-version: '3.4'
73
- bundler-cache: true
74
-
75
- - name: Run StandardRB
76
- run: bundle exec standardrb
data/.gitignore DELETED
@@ -1,37 +0,0 @@
1
- *.gem
2
- *.rbc
3
- /.config
4
- /coverage/
5
- /InstalledFiles
6
- /pkg/
7
- /spec/reports/
8
- /spec/examples.txt
9
- /test/tmp/
10
- /test/version_tmp/
11
- /tmp/
12
- spec/examples.txt
13
- .byebug_history
14
-
15
- ## Documentation cache and generated files
16
- /.yardoc/
17
- /_yardoc/
18
- /doc/
19
- /rdoc/
20
-
21
- ## Environment normalization
22
- /.bundle/
23
- /vendor/bundle
24
- /lib/bundler/man/
25
-
26
- # System files
27
- .DS_Store
28
-
29
- # Editors
30
- .vscode
31
- .ruby-lsp
32
-
33
- # Unnecessary for Ruby gems
34
- Gemfile.lock
35
- .ruby-version
36
- .ruby-gemset
37
- .tool-versions
data/.standard.yml DELETED
@@ -1,9 +0,0 @@
1
- plugins:
2
- - standard-performance
3
- - standard-rspec
4
-
5
- ignore:
6
- - 'spec/**/*_spec.rb':
7
- - RSpec/MultipleMemoizedHelpers
8
- - RSpec/MultipleExpectations
9
- - RSpec/ExampleLength
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,7 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
- require "standard/rake"
4
-
5
- RSpec::Core::RakeTask.new(:spec)
6
-
7
- task default: %i[spec standard]
data/bin/console DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "sidekiq/fairplay"
5
-
6
- require "pry"
7
- Pry.start
data/bin/setup DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec path: "../"
4
-
5
- gem "sidekiq", "~> 7.0"
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec path: "../"
4
-
5
- gem "sidekiq", "~> 8.0"
@@ -1,37 +0,0 @@
1
- lib = File.expand_path("lib", __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "sidekiq/fairplay/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "sidekiq-fairplay"
7
- spec.version = Sidekiq::Fairplay::VERSION
8
- spec.authors = ["Alexander Baygeldin"]
9
- spec.email = ["a.baygeldin@gmail.com"]
10
- spec.summary = <<~SUMMARY
11
- Make Sidekiq play fair — dynamic job prioritization for multi-tenant apps.
12
- SUMMARY
13
- spec.homepage = "http://github.com/baygeldin/sidekiq-fairplay"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.require_paths = ["lib"]
19
-
20
- spec.required_ruby_version = ">= 3.4.0"
21
-
22
- spec.add_development_dependency "bundler", "~> 2.0"
23
- spec.add_development_dependency "pry", "~> 0.15"
24
- spec.add_development_dependency "rake", "~> 13.0"
25
- spec.add_development_dependency "rspec", "~> 3.0"
26
- spec.add_development_dependency "rspec-sidekiq", "~> 5.0"
27
- spec.add_development_dependency "standard", "~> 1.0"
28
- spec.add_development_dependency "standard-performance", "~> 1.0"
29
- spec.add_development_dependency "standard-rspec", "~> 0.3"
30
- spec.add_development_dependency "simplecov", "~> 0.22"
31
- spec.add_development_dependency "timecop", "~> 0.9"
32
-
33
- spec.add_dependency "activesupport", "~> 7.0"
34
- spec.add_runtime_dependency "sidekiq", "~> 7.0"
35
-
36
- spec.metadata["rubygems_mfa_required"] = "true"
37
- end
@@ -1,301 +0,0 @@
1
- require "spec_helper"
2
-
3
- class RegularJob
4
- include Sidekiq::Job
5
-
6
- def perform(foo)
7
- end
8
- end
9
-
10
- class FairplayJob
11
- include Sidekiq::Job
12
- include Sidekiq::Fairplay::Job
13
-
14
- def perform(tenant_key, foo)
15
- end
16
- end
17
-
18
- RSpec.describe Sidekiq::Fairplay do
19
- before do
20
- FairplayJob.sidekiq_fairplay_options \
21
- enqueue_interval:,
22
- enqueue_jobs:,
23
- planner_queue:,
24
- planner_lock_ttl:,
25
- latency_threshold:,
26
- tenant_key:,
27
- tenant_weights:
28
- end
29
-
30
- let(:enqueue_interval) { 1 }
31
- let(:enqueue_jobs) { 10 }
32
- let(:planner_queue) { "default" }
33
- let(:planner_lock_ttl) { 60 }
34
- let(:latency_threshold) { 60 }
35
- let(:tenant_key) { ->(tenant_key, *_args) { tenant_key } }
36
- let(:tenant_weights) { ->(tenant_keys) { tenant_keys.to_h { |tid| [tid, 1] } } }
37
-
38
- describe "fairness (probabilistic)" do
39
- # Seed Ruby's PRNG for deterministic results
40
- around do |example|
41
- prev = srand(1234)
42
- example.run
43
- ensure
44
- srand(prev)
45
- end
46
-
47
- let(:enqueue_jobs) { 1000 }
48
- let(:tenant_weights) do
49
- ->(tenant_ids) do
50
- mapping = {"t1" => 1, "t2" => 3, "t3" => 6}
51
- tenant_ids.to_h { |tid| [tid, mapping.fetch(tid, 1)] }
52
- end
53
- end
54
-
55
- it "enqueues approximately proportional to weights" do
56
- enqueue_jobs.times do |i|
57
- FairplayJob.perform_async("t1", "a#{i}")
58
- FairplayJob.perform_async("t2", "b#{i}")
59
- FairplayJob.perform_async("t3", "c#{i}")
60
- end
61
-
62
- Sidekiq::Fairplay::Planner.new.perform("FairplayJob")
63
-
64
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(enqueue_jobs)
65
-
66
- jobs_per_tenant = FairplayJob.jobs.each_with_object(Hash.new(0)) do |job, memo|
67
- memo[job["args"].first] += 1
68
- end
69
-
70
- expected_jobs_per_tenant = {"t1" => 100, "t2" => 300, "t3" => 600}
71
- tolerance = 0.25 # 25% tolerance to avoid flakiness across Ruby versions
72
-
73
- expected_jobs_per_tenant.each do |tid, exp|
74
- low = (exp * (1 - tolerance)).floor
75
- high = (exp * (1 + tolerance)).ceil
76
-
77
- expect(jobs_per_tenant[tid]).to be_between(low, high).inclusive
78
- end
79
- end
80
- end
81
-
82
- describe "basic functionality" do
83
- it "intercepts fairplay jobs and enqueues them later" do
84
- FairplayJob.perform_async("t1", "a")
85
- FairplayJob.perform_async("t2", "b")
86
- FairplayJob.perform_async("t3", "c")
87
-
88
- expect(FairplayJob).not_to have_enqueued_sidekiq_job
89
- expect(Sidekiq::Fairplay::Planner)
90
- .to have_enqueued_sidekiq_job("FairplayJob")
91
- .exactly(1)
92
- .immediately
93
-
94
- Sidekiq::Fairplay::Planner.perform_one
95
-
96
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(3)
97
- expect(FairplayJob).to have_enqueued_sidekiq_job("t1", "a")
98
- expect(FairplayJob).to have_enqueued_sidekiq_job("t2", "b")
99
- expect(FairplayJob).to have_enqueued_sidekiq_job("t3", "c")
100
- end
101
-
102
- context "with custom planner queue" do
103
- let(:planner_queue) { "whatever" }
104
-
105
- it "enqueues the planner job on the configured queue" do
106
- FairplayJob.perform_async("t1", "a")
107
-
108
- Sidekiq::Fairplay::Planner.perform_one
109
-
110
- expect(Sidekiq::Fairplay::Planner)
111
- .to have_enqueued_sidekiq_job("FairplayJob")
112
- .on(planner_queue)
113
- .in(enqueue_interval.to_i)
114
-
115
- expect(FairplayJob)
116
- .to have_enqueued_sidekiq_job("t1", "a")
117
- .on("default") # default queue for FairplayJob
118
- end
119
- end
120
-
121
- context "when latency threshold exceeded" do
122
- let(:queue) { instance_double(Sidekiq::Queue) }
123
-
124
- before do
125
- allow(Sidekiq::Queue).to receive(:new).and_return(queue)
126
- allow(queue).to receive(:latency).and_return(latency_threshold.to_i + 1)
127
- end
128
-
129
- it "reschedules the planner without enqueuing jobs" do
130
- FairplayJob.perform_async("t1", "a")
131
-
132
- Sidekiq::Fairplay::Planner.perform_one
133
-
134
- expect(FairplayJob).not_to have_enqueued_sidekiq_job
135
- expect(Sidekiq::Fairplay::Planner)
136
- .to have_enqueued_sidekiq_job("FairplayJob")
137
- .in(enqueue_interval.to_i)
138
- end
139
- end
140
-
141
- context "with custom weights" do
142
- let(:tenant_weights) do
143
- ->(tenant_ids) do
144
- tenant_ids.to_h do |tid|
145
- [tid, (tid == "t1") ? 1 : 0]
146
- end
147
- end
148
- end
149
-
150
- it "uses weights to prefer specific tenant" do
151
- FairplayJob.perform_async("t1", "a")
152
- FairplayJob.perform_async("t2", "b")
153
-
154
- Sidekiq::Fairplay::Planner.perform_one
155
-
156
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(1)
157
- expect(FairplayJob).to have_enqueued_sidekiq_job("t1", "a")
158
- expect(FairplayJob).not_to have_enqueued_sidekiq_job("t2", "b")
159
- end
160
- end
161
-
162
- context "when too many jobs in the queue" do
163
- let(:enqueue_jobs) { 1 }
164
-
165
- it "respects the enqueue_jobs limit" do
166
- FairplayJob.perform_async("t1", "a")
167
- FairplayJob.perform_async("t1", "b")
168
-
169
- Sidekiq::Fairplay::Planner.perform_one
170
-
171
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(1)
172
- expect(FairplayJob)
173
- .to have_enqueued_sidekiq_job("t1", "a")
174
- .or have_enqueued_sidekiq_job("t1", "b")
175
- end
176
- end
177
- end
178
-
179
- describe "edge cases" do
180
- it "ignores unknown job class" do
181
- Sidekiq::Fairplay::Planner.new.perform("UnknownJob")
182
-
183
- expect(Sidekiq::Fairplay::Planner).not_to have_enqueued_sidekiq_job
184
- expect(FairplayJob).not_to have_enqueued_sidekiq_job
185
- end
186
-
187
- it "has no effect on regular jobs" do
188
- RegularJob.perform_async("foo")
189
-
190
- expect(RegularJob).to have_enqueued_sidekiq_job("foo")
191
- expect(Sidekiq::Fairplay::Planner).not_to have_enqueued_sidekiq_job
192
- end
193
-
194
- it "has no effect on scheduled jobs" do
195
- FairplayJob.perform_in(5, "t1", "a")
196
-
197
- expect(FairplayJob).to have_enqueued_sidekiq_job("t1", "a").in(5)
198
- expect(Sidekiq::Fairplay::Planner).not_to have_enqueued_sidekiq_job
199
- end
200
-
201
- context "with zero weights for all tenants" do
202
- let(:tenant_weights) do
203
- ->(tenant_ids) { tenant_ids.to_h { |tid| [tid, 0] } }
204
- end
205
-
206
- it "enqueues no jobs" do
207
- FairplayJob.perform_async("t1", "a")
208
- FairplayJob.perform_async("t2", "b")
209
-
210
- Sidekiq::Fairplay::Planner.perform_one
211
-
212
- expect(FairplayJob).not_to have_enqueued_sidekiq_job
213
- end
214
- end
215
- end
216
-
217
- describe "errors" do
218
- let(:tenant_key) { ->(_tid, *_args) {} }
219
-
220
- it "raises when tenant key resolves to nil" do
221
- tenant_key
222
-
223
- expect { FairplayJob.perform_async("t1", "a") }
224
- .to raise_error(ArgumentError, /tenant key cannot be nil/)
225
- end
226
- end
227
-
228
- describe "implementation details" do
229
- it "reschedules planning for the next interval" do
230
- FairplayJob.perform_async("t1", "a")
231
-
232
- Sidekiq::Fairplay::Planner.perform_one
233
-
234
- expect(Sidekiq::Fairplay::Planner)
235
- .to have_enqueued_sidekiq_job("FairplayJob")
236
- .in(enqueue_interval.to_i)
237
- end
238
-
239
- context "when planner_lock_ttl is being held" do
240
- let(:planner_lock_ttl) { 42 }
241
-
242
- before do
243
- redis = Sidekiq::Fairplay::Redis.new
244
- redis.try_acquire_planner_lock(FairplayJob, "some_jid")
245
- end
246
-
247
- it "blocks planning until the TTL expires" do
248
- FairplayJob.perform_async("t1", "a")
249
-
250
- Sidekiq::Fairplay::Planner.perform_one
251
-
252
- expect(FairplayJob).not_to have_enqueued_sidekiq_job
253
- expect(Sidekiq::Fairplay::Planner)
254
- .to have_enqueued_sidekiq_job("FairplayJob")
255
- .in(enqueue_interval.to_i)
256
- end
257
- end
258
-
259
- context "when tenant_key and tenant_weights refer to class methods" do
260
- before do
261
- class << FairplayJob
262
- def static_tenant_key(tid, *_args) = tid
263
- def static_tenant_weights(tids) = tids.to_h { |tid| [tid, 1] }
264
- end
265
- end
266
-
267
- let(:tenant_key) { ->(tid, *args) { static_tenant_key(tid, *args) } }
268
- let(:tenant_weights) { ->(tids) { static_tenant_weights(tids) } }
269
-
270
- it "works as expected" do
271
- FairplayJob.perform_async("t1", "a")
272
- FairplayJob.perform_async("t2", "b")
273
-
274
- Sidekiq::Fairplay::Planner.perform_one
275
-
276
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(2)
277
- expect(FairplayJob).to have_enqueued_sidekiq_job("t1", "a")
278
- expect(FairplayJob).to have_enqueued_sidekiq_job("t2", "b")
279
- end
280
- end
281
-
282
- context "when using ActiveSupport::Duration" do
283
- let(:enqueue_interval) { 1.minute }
284
- let(:latency_threshold) { 1.hour }
285
- let(:planner_lock_ttl) { 10.seconds }
286
-
287
- it "handles durations correctly" do
288
- FairplayJob.perform_async("t1", "a")
289
-
290
- Sidekiq::Fairplay::Planner.perform_one
291
-
292
- expect(Sidekiq::Fairplay::Planner)
293
- .to have_enqueued_sidekiq_job("FairplayJob")
294
- .in(enqueue_interval.to_i)
295
-
296
- expect(FairplayJob).to have_enqueued_sidekiq_job.exactly(1)
297
- expect(FairplayJob).to have_enqueued_sidekiq_job("t1", "a")
298
- end
299
- end
300
- end
301
- end
data/spec/spec_helper.rb DELETED
@@ -1,63 +0,0 @@
1
- $LOAD_PATH << "." unless $LOAD_PATH.include?(".")
2
-
3
- require "rubygems"
4
- require "bundler/setup"
5
- require "timecop"
6
- require "simplecov"
7
-
8
- require "sidekiq"
9
- require "rspec-sidekiq"
10
- require "sidekiq/fairplay"
11
- require "pry"
12
-
13
- SimpleCov.start do
14
- add_filter "spec"
15
- end
16
-
17
- Sidekiq::Fairplay.logger = nil
18
-
19
- Sidekiq.configure_client do |config|
20
- config.redis = {db: 1}
21
- config.logger = nil
22
-
23
- config.client_middleware do |chain|
24
- chain.add Sidekiq::Fairplay::Middleware
25
- end
26
- end
27
-
28
- Sidekiq.configure_server do |config|
29
- config.redis = {db: 1}
30
- config.logger = nil
31
-
32
- config.client_middleware do |chain|
33
- chain.add Sidekiq::Fairplay::Middleware
34
- end
35
- end
36
-
37
- RSpec::Sidekiq.configure do |config|
38
- config.clear_all_enqueued_jobs = true
39
- config.warn_when_jobs_not_processed_by_sidekiq = false
40
- end
41
-
42
- RSpec.configure do |config|
43
- config.order = :random
44
- config.run_all_when_everything_filtered = true
45
- config.example_status_persistence_file_path = "spec/examples.txt"
46
-
47
- config.before do
48
- Sidekiq.redis do |conn|
49
- keys = conn.call("KEYS", "fairplay*")
50
- keys.each { |key| conn.call("DEL", key) }
51
- end
52
- end
53
-
54
- config.before do
55
- Timecop.freeze
56
- end
57
-
58
- config.after do
59
- Timecop.return
60
- end
61
- end
62
-
63
- $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")