sidekiq-robust-job 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c4c75298ef6032a3493a8b34871ba84575d1e59fa0d8a21088b3290542b74b3
4
- data.tar.gz: 05d1a83d06300c4f273553f07a6ecc38a78f9eddea8539e1d7b85345d53de2f9
3
+ metadata.gz: 29ab88d61f30457510da2f336be215a6604f2375583b16b7eaf608fe34cb37c5
4
+ data.tar.gz: c6a174c766334dee3ca28c9dc43b865f1d0f38b8bfce2021e2bcafeaab2b4724
5
5
  SHA512:
6
- metadata.gz: f9e79a683e532d8078975b9e876db178218a5c5e2937cd734f61c37107f5a1d53b62ee95f8f4d7cf96c7869a970fcf919965420ec75df84029f2d8847574d3ff
7
- data.tar.gz: 31067138cd1c737ccc690908b5e75d12fa7d8d5e7f55e086834566ff2e115d4b2664c6b56126880d44468fe6c7953dd3eebd99f49464c8490087b5180104add2
6
+ metadata.gz: 94388670e901388a0958d15715b4371235e6ef81e8dae86dd57f2340734fc911330c656bee9f39b11af897edcce0b6398e1214609fbb7f5de1a09fdcb5498b7d
7
+ data.tar.gz: 93ec3981822acf52de3b8191d88c9ef4fe904674412a43d498b4d1dd06ad395ef19321e303f72475685ce74696a8e6d18a691c67018e4b7a046163e70ba1bbd1
@@ -1,4 +1,7 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0
4
+ - Introduce `persist_self_dropped_jobs` config option
5
+
3
6
  ## 0.1.0
4
7
  - Initial release
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sidekiq-robust-job (0.1.0)
4
+ sidekiq-robust-job (0.2.0)
5
5
  activesupport (>= 5)
6
6
  sidekiq (>= 5)
7
7
  sidekiq-cron (~> 1)
@@ -47,7 +47,7 @@ GEM
47
47
  factory_bot_rails (6.1.0)
48
48
  factory_bot (~> 6.1.0)
49
49
  railties (>= 5.0.0)
50
- fugit (1.4.0)
50
+ fugit (1.4.1)
51
51
  et-orbi (~> 1.1, >= 1.1.8)
52
52
  raabro (~> 1.4)
53
53
  i18n (1.8.5)
data/README.md CHANGED
@@ -57,6 +57,7 @@ class CreateSidekiqJobs < ActiveRecord::Migration[6.0]
57
57
  t.datetime "execute_at"
58
58
  t.string "sidekiq_jid"
59
59
 
60
+ t.index ["completed_at", "failed_at", "dropped_at"], name: "index_sidekiq_jobs_on_completed_at_and_failed_at_and_dropped_at"
60
61
  t.index ["completed_at"], name: "index_sidekiq_jobs_on_completed_at", using: :brin
61
62
  t.index ["created_at"], name: "index_sidekiq_jobs_on_created_at", using: :brin
62
63
  t.index ["digest"], name: "index_sidekiq_jobs_on_digest"
@@ -144,6 +145,25 @@ Although keep in mind that using this feature comes with some performance penalt
144
145
 
145
146
  If you have a lot of conflicts within a short period, consider using `perform_in` instead of `perform_async` and add some random number of seconds (ideally, below 1 minute) to make it easier to apply enqueue conflict resolution strategy.
146
147
 
148
+ If you enqueue a lot of the same jobs (same class, same arguments) in a short period of time and `drop_self` strategy, you should consider setting `persist_self_dropped_jobs` config option to false. By default, it's true which means that even the jobs that are dropped are persisted, which might be useful for some profiling or even figuring out in the first place that you have an issue like this. However, under such circumstances this is likely to result in heavier queries fetching a lot of rows from the database, causing a high database load.
149
+
150
+ Here is an example how to use it:
151
+
152
+
153
+ ``` rb
154
+ class MyJob
155
+ include Sidekiq::Worker
156
+ include SidekiqRobustJob::SidekiqJobExtensions
157
+
158
+ sidekiq_options queue: "critical", enqueue_conflict_resolution_strategy: "drop_self",
159
+ persist_self_dropped_jobs: false
160
+
161
+ def call(user_id)
162
+ User.find(user_id).do_something
163
+ end
164
+ end
165
+ ```
166
+
147
167
  #### Execution Uniqueness (Mutex)
148
168
 
149
169
  This feature is about handling a "conflict" (determined by a digest generated based on the job class and its arguments) when there is already the "same job" getting executed (i.e. same job class and arguments) at the same time.
@@ -269,12 +289,19 @@ expect {
269
289
  }.to enqueue_sidekiq_robust_job(MyJob).with(user.id).at(5.seconds.from_now)
270
290
  ```
271
291
 
292
+
293
+ There is also a negated matcher: `not_enqueue_sidekiq_robust_job`.
294
+
272
295
  ### How to migrate already enqueued jobs when introducing the gem?
273
296
 
274
297
  This might be a bit tricky. You might consider using new job classes temporarily so that the already existing jobs are performed and the new ones are getting enqueued and then use again the original class with `SidekiqRobustJob::SidekiqJobExtensions` included and `call` method defined.
275
298
 
276
299
  You can also stop workers, iterate over all existing jobs, re-schedule them (after including the module) and delete them - it's safe because the actual job will still be there, but it will be enqueued this time with job's ID and `call` method will be used. And you need to delete the original ones as they might have either a different `perform` method signature, or when having the same one, the argument will have a different meaning that job's ID, which can cause an unexpected behavior. This might require a downtime if you are not able to distinguish just based on the arguments of the job between the previous way of executing jobs and the new one. If you are able to, the downtime might not be required, but a lot of jobs can fail due to `perform` method's signature change. However, you can also re-enqueue these jobs and delete them from `RetrySet`.
277
300
 
301
+ ### Maintenance
302
+
303
+ It is recommended to periodically remove old jobs for the maximum performance. [Tartarus](https://github.com/BookingSync/tartarus-rb) is a recommended approach for that.
304
+
278
305
  ## Development
279
306
 
280
307
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,7 +1,7 @@
1
1
  module Sidekiq
2
2
  module Robust
3
3
  module Job
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -4,7 +4,6 @@ class SidekiqRobustJob
4
4
  def execute(job)
5
5
  if jobs_repository.unprocessed_for_digest(job.digest, exclude_id: job.id).any?
6
6
  job.drop(dropped_by_job_id: job.id, clock: clock)
7
- jobs_repository.save(job)
8
7
  end
9
8
  end
10
9
  end
@@ -17,13 +17,17 @@ class SidekiqRobustJob
17
17
  end
18
18
 
19
19
  def save(record)
20
- record.save!
20
+ record.save! if record.changed?
21
21
  end
22
22
 
23
23
  def create(attributes)
24
24
  jobs_database.create!(attributes)
25
25
  end
26
26
 
27
+ def build(attributes)
28
+ jobs_database.new(attributes)
29
+ end
30
+
27
31
  def missed_jobs(missed_job_policy:)
28
32
  jobs_database
29
33
  .where(completed_at: nil, dropped_at: nil, failed_at: nil)
@@ -53,7 +53,7 @@ class SidekiqRobustJob
53
53
  private
54
54
 
55
55
  def create_job(job_class, *arguments)
56
- jobs_repository.create(
56
+ jobs_repository.build(
57
57
  job_class: job_class,
58
58
  arguments: Array.wrap(arguments),
59
59
  enqueued_at: clock.now,
@@ -64,9 +64,10 @@ class SidekiqRobustJob
64
64
  enqueue_conflict_resolution_strategy: job_class.get_sidekiq_options.fetch("enqueue_conflict_resolution_strategy",
65
65
  SidekiqRobustJob::EnqueueConflictResolutionStrategy.do_nothing)
66
66
  ).tap do |job|
67
+ jobs_repository.save(job) if persist_job_immediately?(job_class)
67
68
  jobs_repository.transaction do
68
69
  resolve_potential_conflict_for_enqueueing(job)
69
- jobs_repository.save(job)
70
+ jobs_repository.save(job) if persist_after_resolving_conflict_for_enqueueing(job, job_class)
70
71
  end
71
72
  end
72
73
  end
@@ -76,5 +77,19 @@ class SidekiqRobustJob
76
77
  .resolve(job.enqueue_conflict_resolution_strategy)
77
78
  .execute(job)
78
79
  end
80
+
81
+ def persist_job_immediately?(job_class)
82
+ persist_self_dropped_jobs?(job_class)
83
+ end
84
+
85
+ def persist_after_resolving_conflict_for_enqueueing(job, job_class)
86
+ return true if persist_self_dropped_jobs?(job_class)
87
+
88
+ !job.dropped?
89
+ end
90
+
91
+ def persist_self_dropped_jobs?(job_class)
92
+ job_class.get_sidekiq_options.fetch("persist_self_dropped_jobs", true)
93
+ end
79
94
  end
80
95
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-robust-job
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-18 00:00:00.000000000 Z
11
+ date: 2021-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq