acidic_job 1.0.0.pre10 → 1.0.0.pre11

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: 95b8fbdebe38a639f9b905df6ac1f5b853b09383d0810696c89c6c9e001efffe
4
- data.tar.gz: b7e92f9b98461e2f39122405b6e3278fb7ed8a0edec65963026f7e2665bb5042
3
+ metadata.gz: 53b5f12879bffb6a461e3574b96f8a41464ec83ce0a21eaa8e244261ce53a9be
4
+ data.tar.gz: 7b90c9864347564706466e62c61f08eb377d8e3a33475ad40ba559de59e7b70e
5
5
  SHA512:
6
- metadata.gz: 13b5ea59163e833f5b698625d841fdcdc0a630b46880526df3274926e696b227b41946fd6622e121b9afd90ad3cc94589f6e864188e871d70f03c77168e3ad5e
7
- data.tar.gz: 27e5b74147706f227875f4f4a61f084298c42e615149cb0a74670af841df8fcce9eb4f95d11935561912af61d6d8759c21c9ca9862e897f765b49c78b1e42ebd
6
+ metadata.gz: '08b4a0bdd41ac80f8ac879003f455f577f93fc431acdb780dfd3e54260b07a61bf0557c3e7d99192e1ad809134b709211fd2c5efe581b797563187dcfbb34467'
7
+ data.tar.gz: 66e8b3bfe0226c3e1f5168d45431a01a36ee3dfb796c855c49fc009296cb223d33922bc2db5febbe6d6453b4a01c46661b805aa1e2c80a4e37f3dce183b5e748
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acidic_job (1.0.0.pre10)
4
+ acidic_job (1.0.0.pre11)
5
5
  activerecord (>= 6.1.0)
6
6
  activesupport
7
7
 
data/README.md CHANGED
@@ -64,6 +64,7 @@ It provides a suite of functionality that empowers you to create complex, robust
64
64
  * Transactional Steps — break your job into a series of steps, each of which will be run within an acidic database transaction, allowing retries to jump back to the last "recovery point".
65
65
  * Persisted Attributes — when retrying jobs at later steps, we need to ensure that data created in previous steps is still available to later steps on retry.
66
66
  * Transactionally Staged Jobs — enqueue additional jobs within the acidic transaction safely
67
+ * Custom Idempotency Keys — use something other than the job ID for the idempotency key of the job run
67
68
  * Sidekiq Callbacks — bring ActiveJob-like callbacks into your pure Sidekiq Workers
68
69
  * Sidekiq Batches — leverage the power of Sidekiq Pro's `batch` functionality without the hassle
69
70
 
@@ -163,6 +164,47 @@ class RideCreateJob < ActiveJob::Base
163
164
  end
164
165
  ```
165
166
 
167
+ ### Custom Idempotency Keys
168
+
169
+ By default, `AcidicJob` uses the job identifier provided by the queueing system (ActiveJob or Sidekiq) as the idempotency key for the job run. The idempotency key is what is used to guarantee that no two runs of the same job occur. However, sometimes we need particular jobs to be idempotent based on some other criteria. In these cases, `AcidicJob` provides a collection of tools to allow you to ensure the idempotency of your jobs.
170
+
171
+ Firstly, you can configure your job class to explicitly use either the job identifier or the job arguments as the foundation for the idempotency key. A job class that calls the `acidic_by_job_id` class method (which is the default behavior) will simply make the job run's idempotency key the job's identifier:
172
+
173
+ ```ruby
174
+ class ExampleJob < ActiveJob::Base
175
+ include AcidicJob
176
+ acidic_by_job_id
177
+
178
+ def perform
179
+ end
180
+ end
181
+ ```
182
+
183
+ Conversely, a job class can use the `acidic_by_job_args` method to configure that job class to use the arguments passed to the job as the foundation for the job run's idempotency key:
184
+
185
+ ```ruby
186
+ class ExampleJob < ActiveJob::Base
187
+ include AcidicJob
188
+ acidic_by_job_args
189
+
190
+ def perform(arg_1, arg_2)
191
+ # the idempotency key will be based on whatever the values of `arg_1` and `arg_2` are
192
+ end
193
+ end
194
+ ```
195
+
196
+ These options cover the two common situations, but sometimes our systems need finer-grained control. For example, our job might take some record as the job argument, but we need to use a combination of the record identifier and record status as the foundation for the idempotency key. In these cases we can't configure the idempotency key logic at the class level, so instead we can provide the logic when enqueuing the job itself.
197
+
198
+ When you call any `deliver_acidicly` or `perform_acidicly` method you can pass an optional `unique_by` argument which will be used to generate the idempotency key:
199
+
200
+ ```ruby
201
+ ExampleJob.perform_acidicly(unique_by: { id: record.id, status: record.status })
202
+ UserMailer.with(user, record).deliver_acidicly(unique_by: [user.id, record.id, record.status])
203
+ ```
204
+
205
+ As you see, the value to the `unique_by` option can be a Hash or an Array or even a simple scalar value.
206
+
207
+
166
208
  ### Sidekiq Callbacks
167
209
 
168
210
  In order to ensure that `AcidicJob::Staged` records are only destroyed once the related job has been successfully performed, whether it is an ActiveJob or a Sidekiq Worker, `acidic_job` also extends Sidekiq to support the [ActiveJob callback interface](https://edgeguides.rubyonrails.org/active_job_basics.html#callbacks).
@@ -7,17 +7,15 @@ module AcidicJob
7
7
  module ActionMailer
8
8
  extend ActiveSupport::Concern
9
9
 
10
- def deliver_acidicly(_options = {}, idempotency_key: nil, unique_by: nil)
10
+ def deliver_acidicly(_options = {}, unique_by: nil)
11
11
  job_class = ::ActionMailer::MailDeliveryJob
12
12
 
13
13
  job_args = [@mailer_class.name, @action.to_s, "deliver_now", @params, *@args]
14
14
  # for Sidekiq, this depends on the Sidekiq::Serialization extension
15
15
  serialized_job = job_class.new(job_args).serialize
16
16
  acidic_identifier = job_class.respond_to?(:acidic_identifier) ? job_class.acidic_identifier : :job_id
17
- # use either [1] provided key, [2] provided uniqueness constraint, or [3] computed key
18
- key = if idempotency_key
19
- idempotency_key
20
- elsif unique_by
17
+ # use either [1] provided uniqueness constraint or [2] computed key
18
+ key = if unique_by
21
19
  IdempotencyKey.generate(unique_by: unique_by, job_class: job_class.name)
22
20
  else
23
21
  IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
@@ -24,10 +24,8 @@ module AcidicJob
24
24
  raise UnsupportedExtension unless defined?(::ActiveJob) && self < ::ActiveJob::Base
25
25
 
26
26
  serialized_job = serialize_with_arguments(*args, **kwargs)
27
- # use either [1] provided key, [2] provided uniqueness constraint, or [3] computed key
28
- key = if kwargs.key?(:idempotency_key) || kwargs.key?("idempotency_key")
29
- kwargs[:idempotency_key] || kwargs["idempotency_key"]
30
- elsif kwargs.key?(:unique_by) || kwargs.key?("unique_by")
27
+ # use either [1] provided uniqueness constraint or [2] computed key
28
+ key = if kwargs.key?(:unique_by) || kwargs.key?("unique_by")
31
29
  unique_by = [kwargs[:unique_by], kwargs["unique_by"]].compact.first
32
30
  IdempotencyKey.generate(unique_by: unique_by, job_class: name)
33
31
  else
@@ -6,12 +6,12 @@ module AcidicJob
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  class_methods do
9
- def deliver_acidicly(recipients, idempotency_key: nil, unique_by: nil)
10
- new.deliver_acidicly(recipients, idempotency_key: idempotency_key, unique_by: unique_by)
9
+ def deliver_acidicly(recipients, unique_by: nil)
10
+ new.deliver_acidicly(recipients, unique_by: unique_by)
11
11
  end
12
12
  end
13
13
 
14
- def deliver_acidicly(recipients, idempotency_key: nil, unique_by: nil)
14
+ def deliver_acidicly(recipients, unique_by: nil)
15
15
  # THIS IS A HACK THAT COPIES AND PASTES KEY PARTS OF THE `Noticed::Base` CODE
16
16
  # IN ORDER TO ALLOW US TO TRANSACTIONALLY DELIVER NOTIFICATIONS
17
17
  # THIS IS THUS LIABLE TO BREAK WHENEVER THAT GEM IS UPDATED
@@ -37,10 +37,8 @@ module AcidicJob
37
37
  }
38
38
  serialized_job = job_class.send(:job_or_instantiate, args).serialize
39
39
  acidic_identifier = job_class.respond_to?(:acidic_identifier) ? job_class.acidic_identifier : :job_id
40
- # use either [1] provided key, [2] provided uniqueness constraint, or [3] computed key
41
- key = if idempotency_key
42
- idempotency_key
43
- elsif unique_by
40
+ # use either [1] provided uniqueness constraint or [2] computed key
41
+ key = if unique_by
44
42
  IdempotencyKey.generate(unique_by: unique_by, job_class: job_class.name)
45
43
  else
46
44
  IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
@@ -58,10 +58,8 @@ module AcidicJob
58
58
  class_methods do
59
59
  def perform_acidicly(*args, **kwargs)
60
60
  serialized_job = serialize_with_arguments(*args, **kwargs)
61
- # use either [1] provided key, [2] provided uniqueness constraint, or [3] computed key
62
- key = if kwargs.key?(:idempotency_key) || kwargs.key?("idempotency_key")
63
- kwargs[:idempotency_key] || kwargs["idempotency_key"]
64
- elsif kwargs.key?(:unique_by) || kwargs.key?("unique_by")
61
+ # use either [1] provided uniqueness constraint or [2] computed key
62
+ key = if kwargs.key?(:unique_by) || kwargs.key?("unique_by")
65
63
  unique_by = [kwargs[:unique_by], kwargs["unique_by"]].compact.first
66
64
  IdempotencyKey.generate(unique_by: unique_by, job_class: name)
67
65
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AcidicJob
4
- VERSION = "1.0.0.pre10"
4
+ VERSION = "1.0.0.pre11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acidic_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre10
4
+ version: 1.0.0.pre11
5
5
  platform: ruby
6
6
  authors:
7
7
  - fractaledmind