README.md in sidekiq-unique-jobs-6.0.0.rc7 vs README.md in sidekiq-unique-jobs-6.0.0.rc8
- old
+ new
@@ -7,27 +7,34 @@
* [Requirements](#requirements)
* [Installation](#installation)
* [Support Me](#support-me)
* [General Information](#general-information)
* [Options](#options)
- * [Lock Expiration](#lock-expiration)
- * [Lock Timeout](#lock-timeout)
- * [Unique Across Queues](#unique-across-queues)
- * [Unique Across Workers](#unique-across-workers)
+ * [Lock Expiration](#lock-expiration)
+ * [Lock Timeout](#lock-timeout)
+ * [Unique Across Queues](#unique-across-queues)
+ * [Unique Across Workers](#unique-across-workers)
* [Locks](#locks)
- * [Until Executing](#until-executing)
- * [Until Executed](#until-executed)
- * [Until Timeout](#until-timeout)
- * [Unique Until And While Executing](#unique-until-and-while-executing)
- * [While Executing](#while-executing)
+ * [Until Executing](#until-executing)
+ * [Until Executed](#until-executed)
+ * [Until Timeout](#until-timeout)
+ * [Unique Until And While Executing](#unique-until-and-while-executing)
+ * [While Executing](#while-executing)
* [Conflict Strategy](#conflict-strategy)
+ * [Log](#log)
+ * [Raise](#raise)
+ * [Reject](#reject)
+ * [Replace](#replace)
+ * [Reschedule](#reschedule)
* [Usage](#usage)
- * [Finer Control over Uniqueness](#finer-control-over-uniqueness)
- * [After Unlock Callback](#after-unlock-callback)
- * [Logging](#logging)
+ * [Finer Control over Uniqueness](#finer-control-over-uniqueness)
+ * [After Unlock Callback](#after-unlock-callback)
+ * [Logging](#logging)
* [Debugging](#debugging)
- * [Sidekiq Web](#sidekiq-web)
+ * [Sidekiq Web](#sidekiq-web)
+ * [Show Unique Digests](#show-unique-digests)
+ * [Show keys for digest](#show-keys-for-digest)
* [Communication](#communication)
* [Testing](#testing)
* [Contributing](#contributing)
* [Contributors](#contributors)
@@ -106,11 +113,11 @@
```ruby
class Worker
include Sidekiq::Worker
- sidekiq_options: unique_across_queues: true, queue: 'default'
+ sidekiq_options unique_across_queues: true, queue: 'default'
def perform(args); end
end
```
@@ -122,19 +129,19 @@
```ruby
class WorkerOne
include Sidekiq::Worker
- sidekiq_options: unique_across_workers: true, queue: 'default'
+ sidekiq_options unique_across_workers: true, queue: 'default'
def perform(args); end
end
class WorkerTwo
include Sidekiq::Worker
- sidekiq_options: unique_across_workers: true, queue: 'default'
+ sidekiq_options unique_across_workers: true, queue: 'default'
def perform(args); end
end
@@ -214,10 +221,16 @@
Decides how we handle conflict. We can either reject the job to the dead queue or reschedule it. Both are useful for jobs that absolutely need to run and have been configured to use the lock `WhileExecuting` that is used only by the sidekiq server process.
The last one is log which can be be used with the lock `UntilExecuted` and `UntilExpired`. Now we write a log entry saying the job could not be pushed because it is a duplicate of another job with the same arguments
+### Log
+
+This strategy is intended to be used with `UntilExecuted` and `UntilExpired`. It will log a line about that this is job is a duplicate of another.
+
+`sidekiq_options lock: :until_executed, on_conflict: :log`
+
### Raise
This strategy is intended to be used with `WhileExecuting`. Basically it will allow us to let the server process crash with a specific error message and be retried without messing up the Sidekiq stats.
`sidekiq_options lock: :while_executing, on_conflict: :raise, retry: 10`
@@ -226,22 +239,27 @@
This strategy is intended to be used with `WhileExecuting` and will push the job to the dead queue on conflict.
`sidekiq_options lock: :while_executing, on_conflict: :reject`
-### Reschedule
+### Replace
-This strategy is intended to be used with `WhileExecuting` and will delay the job to be tried again in 5 seconds. This will mess up the sidekiq stats but will prevent exceptions from being logged and confuse your sysadmins.
+This strategy is intended to be used with client locks like `UntilExecuted`.
+It will delete any existing job for these arguments from retry, schedule and
+queue and retry the lock again.
-`sidekiq_options lock: :while_executing, on_conflict: :reschedule`
+This is slightly dangerous and should probably only be used for jobs that are
+always scheduled in the future. Currently only attempting to retry one time.
-### Log
+`sidekiq_options lock: :until_executed, on_conflict: :replace`
-This strategy is intended to be used with `UntilExecuted` and `UntilExpired`. It will log a line about that this is job is a duplicate of another.
+### Reschedule
-`sidekiq_options lock: :until_executed, on_conflict: :log`
+This strategy is intended to be used with `WhileExecuting` and will delay the job to be tried again in 5 seconds. This will mess up the sidekiq stats but will prevent exceptions from being logged and confuse your sysadmins.
+`sidekiq_options lock: :while_executing, on_conflict: :reschedule`
+
## Usage
All that is required is that you specifically set the sidekiq option for _unique_ to a valid value like below:
```ruby
@@ -376,9 +394,47 @@
```ruby
SidekiqUniqueJobs.configure do |config|
config.enabled = !Rails.env.test?
end
```
+
+If you truly wanted to test the sidekiq client push you could do something like below. Note that it will only work for the jobs that lock when the client pushes the job to redis (UntilExecuted, UntilAndWhileExecuting and UntilExpired).
+
+```ruby
+RSpec.describe Workers::CoolOne do
+ before do
+ SidekiqUniqueJobs.config.enabled = false
+ end
+
+ # ... your tests that don't test uniqueness
+
+ context 'when Sidekiq::Testing.disabled?' do
+ before do
+ Sidekiq::Testing.disable!
+ Sidekiq.redis(&:flushdb)
+ end
+
+ after do
+ Sidekiq.redis(&:flushdb)
+ end
+
+ it 'prevents duplicate jobs from being scheduled' do
+ SidekiqUniqueJobs.use_config(enabled: true) do
+ expect(described_class.perform_async(1)).not_to eq(nil)
+ expect(described_class.perform_async(1)).to eq(nil)
+ end
+ end
+ end
+end
+```
+
+I would strongly suggest you let this gem test uniqueness. If you care about how the gem is integration tested have a look at the following specs:
+
+- [spec/integration/sidekiq_unique_jobs/lock/until_and_while_executing_spec.rb](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/spec/integration/sidekiq_unique_jobs/lock/until_and_while_executing_spec.rb)
+- [spec/integration/sidekiq_unique_jobs/lock/until_executed_spec.rb](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/spec/integration/sidekiq_unique_jobs/lock/until_executed_spec.rb)
+- [spec/integration/sidekiq_unique_jobs/lock/until_expired_spec.rb](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/spec/integration/sidekiq_unique_jobs/lock/until_expired_spec.rb)
+- [spec/integration/sidekiq_unique_jobs/lock/while_executing_reject_spec.rb](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/spec/integration/sidekiq_unique_jobs/lock/while_executing_reject_spec.rb)
+- [spec/integration/sidekiq_unique_jobs/lock/while_executing_spec.rb](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/spec/integration/sidekiq_unique_jobs/lock/while_executing_spec.rb)
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)