acidic_job 1.0.0.pre29 → 1.0.0.rc2
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 +4 -4
- data/.codacy.yml +4 -0
- data/.github/FUNDING.yml +13 -0
- data/.github/workflows/main.yml +12 -15
- data/.gitignore +3 -1
- data/.rubocop.yml +50 -5
- data/.ruby-version +1 -0
- data/Gemfile.lock +134 -193
- data/README.md +164 -246
- data/TODO +77 -0
- data/acidic_job.gemspec +10 -10
- data/app/models/acidic_job/entry.rb +19 -0
- data/app/models/acidic_job/execution.rb +50 -0
- data/app/models/acidic_job/record.rb +11 -0
- data/app/models/acidic_job/value.rb +7 -0
- data/bin/console +5 -2
- data/bin/test_all +26 -0
- data/gemfiles/rails_7.0.gemfile +4 -1
- data/gemfiles/rails_7.1.gemfile +11 -0
- data/gemfiles/rails_7.2.gemfile +11 -0
- data/gemfiles/rails_8.0.gemfile +11 -0
- data/lib/acidic_job/arguments.rb +31 -0
- data/lib/acidic_job/builder.rb +29 -0
- data/lib/acidic_job/context.rb +46 -0
- data/lib/acidic_job/engine.rb +46 -0
- data/lib/acidic_job/errors.rb +87 -12
- data/lib/acidic_job/log_subscriber.rb +50 -0
- data/lib/acidic_job/serializers/exception_serializer.rb +31 -0
- data/lib/acidic_job/serializers/job_serializer.rb +27 -0
- data/lib/acidic_job/serializers/new_record_serializer.rb +25 -0
- data/lib/acidic_job/serializers/range_serializer.rb +28 -0
- data/lib/acidic_job/testing.rb +8 -12
- data/lib/acidic_job/version.rb +1 -1
- data/lib/acidic_job/workflow.rb +182 -0
- data/lib/acidic_job.rb +15 -284
- data/lib/generators/acidic_job/install_generator.rb +3 -3
- data/lib/generators/acidic_job/templates/create_acidic_job_tables_migration.rb.erb +33 -0
- metadata +51 -95
- data/.ruby_version +0 -1
- data/.tool-versions +0 -1
- data/gemfiles/rails_6.1.gemfile +0 -8
- data/lib/acidic_job/awaiting.rb +0 -102
- data/lib/acidic_job/extensions/action_mailer.rb +0 -29
- data/lib/acidic_job/extensions/active_job.rb +0 -40
- data/lib/acidic_job/extensions/noticed.rb +0 -54
- data/lib/acidic_job/extensions/sidekiq.rb +0 -111
- data/lib/acidic_job/finished_point.rb +0 -16
- data/lib/acidic_job/idempotency_key.rb +0 -82
- data/lib/acidic_job/perform_wrapper.rb +0 -22
- data/lib/acidic_job/recovery_point.rb +0 -18
- data/lib/acidic_job/rspec_configuration.rb +0 -31
- data/lib/acidic_job/run.rb +0 -100
- data/lib/acidic_job/serializer.rb +0 -163
- data/lib/acidic_job/staging.rb +0 -38
- data/lib/acidic_job/step.rb +0 -104
- data/lib/acidic_job/test_case.rb +0 -9
- data/lib/acidic_job/upgrade_service.rb +0 -118
- data/lib/generators/acidic_job/drop_tables_generator.rb +0 -26
- data/lib/generators/acidic_job/templates/create_acidic_job_runs_migration.rb.erb +0 -19
- data/lib/generators/acidic_job/templates/drop_acidic_job_keys_migration.rb.erb +0 -27
metadata
CHANGED
@@ -1,101 +1,100 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acidic_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fractaledmind
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-05-14 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
13
|
+
name: json
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
16
|
- - ">="
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
18
|
+
version: 2.7.0
|
20
19
|
type: :runtime
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
23
|
- - ">="
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
25
|
+
version: 2.7.0
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
27
|
+
name: activejob
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
30
|
- - ">="
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
32
|
+
version: '7.1'
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
37
36
|
requirements:
|
38
37
|
- - ">="
|
39
38
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
39
|
+
version: '7.1'
|
41
40
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
41
|
+
name: activerecord
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
44
|
- - ">="
|
46
45
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
46
|
+
version: '7.1'
|
48
47
|
type: :runtime
|
49
48
|
prerelease: false
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
51
50
|
requirements:
|
52
51
|
- - ">="
|
53
52
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
53
|
+
version: '7.1'
|
55
54
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
55
|
+
name: activesupport
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
58
|
- - ">="
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
62
|
-
type: :
|
60
|
+
version: '7.1'
|
61
|
+
type: :runtime
|
63
62
|
prerelease: false
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
65
64
|
requirements:
|
66
65
|
- - ">="
|
67
66
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
67
|
+
version: '7.1'
|
69
68
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
69
|
+
name: railties
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
72
71
|
requirements:
|
73
72
|
- - ">="
|
74
73
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
76
|
-
type: :
|
74
|
+
version: '7.1'
|
75
|
+
type: :runtime
|
77
76
|
prerelease: false
|
78
77
|
version_requirements: !ruby/object:Gem::Requirement
|
79
78
|
requirements:
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
81
|
+
version: '7.1'
|
83
82
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
83
|
+
name: actionmailer
|
85
84
|
requirement: !ruby/object:Gem::Requirement
|
86
85
|
requirements:
|
87
86
|
- - ">="
|
88
87
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
88
|
+
version: '7.1'
|
90
89
|
type: :development
|
91
90
|
prerelease: false
|
92
91
|
version_requirements: !ruby/object:Gem::Requirement
|
93
92
|
requirements:
|
94
93
|
- - ">="
|
95
94
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
95
|
+
version: '7.1'
|
97
96
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
97
|
+
name: chaotic_job
|
99
98
|
requirement: !ruby/object:Gem::Requirement
|
100
99
|
requirements:
|
101
100
|
- - ">="
|
@@ -109,7 +108,7 @@ dependencies:
|
|
109
108
|
- !ruby/object:Gem::Version
|
110
109
|
version: '0'
|
111
110
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
111
|
+
name: combustion
|
113
112
|
requirement: !ruby/object:Gem::Requirement
|
114
113
|
requirements:
|
115
114
|
- - ">="
|
@@ -123,21 +122,7 @@ dependencies:
|
|
123
122
|
- !ruby/object:Gem::Version
|
124
123
|
version: '0'
|
125
124
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '4.0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '4.0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: railties
|
125
|
+
name: minitest
|
141
126
|
requirement: !ruby/object:Gem::Requirement
|
142
127
|
requirements:
|
143
128
|
- - ">="
|
@@ -206,20 +191,6 @@ dependencies:
|
|
206
191
|
- - ">="
|
207
192
|
- !ruby/object:Gem::Version
|
208
193
|
version: '0'
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: sidekiq
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
212
|
-
requirements:
|
213
|
-
- - ">="
|
214
|
-
- !ruby/object:Gem::Version
|
215
|
-
version: '0'
|
216
|
-
type: :development
|
217
|
-
prerelease: false
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
219
|
-
requirements:
|
220
|
-
- - ">="
|
221
|
-
- !ruby/object:Gem::Version
|
222
|
-
version: '0'
|
223
194
|
- !ruby/object:Gem::Dependency
|
224
195
|
name: simplecov
|
225
196
|
requirement: !ruby/object:Gem::Requirement
|
@@ -248,20 +219,6 @@ dependencies:
|
|
248
219
|
- - ">="
|
249
220
|
- !ruby/object:Gem::Version
|
250
221
|
version: '0'
|
251
|
-
- !ruby/object:Gem::Dependency
|
252
|
-
name: warning
|
253
|
-
requirement: !ruby/object:Gem::Requirement
|
254
|
-
requirements:
|
255
|
-
- - ">="
|
256
|
-
- !ruby/object:Gem::Version
|
257
|
-
version: '0'
|
258
|
-
type: :development
|
259
|
-
prerelease: false
|
260
|
-
version_requirements: !ruby/object:Gem::Requirement
|
261
|
-
requirements:
|
262
|
-
- - ">="
|
263
|
-
- !ruby/object:Gem::Version
|
264
|
-
version: '0'
|
265
222
|
description: Idempotent operations for Rails apps, built on top of ActiveJob.
|
266
223
|
email:
|
267
224
|
- stephen.margheim@gmail.com
|
@@ -269,48 +226,49 @@ executables: []
|
|
269
226
|
extensions: []
|
270
227
|
extra_rdoc_files: []
|
271
228
|
files:
|
229
|
+
- ".codacy.yml"
|
230
|
+
- ".github/FUNDING.yml"
|
272
231
|
- ".github/workflows/main.yml"
|
273
232
|
- ".gitignore"
|
274
233
|
- ".rubocop.yml"
|
275
|
-
- ".
|
276
|
-
- ".tool-versions"
|
234
|
+
- ".ruby-version"
|
277
235
|
- Gemfile
|
278
236
|
- Gemfile.lock
|
279
237
|
- LICENSE
|
280
238
|
- README.md
|
281
239
|
- Rakefile
|
240
|
+
- TODO
|
282
241
|
- UPGRADE_GUIDE.md
|
283
242
|
- acidic_job.gemspec
|
243
|
+
- app/models/acidic_job/entry.rb
|
244
|
+
- app/models/acidic_job/execution.rb
|
245
|
+
- app/models/acidic_job/record.rb
|
246
|
+
- app/models/acidic_job/value.rb
|
284
247
|
- bin/console
|
285
248
|
- bin/setup
|
249
|
+
- bin/test_all
|
286
250
|
- blog_post.md
|
287
251
|
- combustion/log/test.log
|
288
|
-
- gemfiles/rails_6.1.gemfile
|
289
252
|
- gemfiles/rails_7.0.gemfile
|
253
|
+
- gemfiles/rails_7.1.gemfile
|
254
|
+
- gemfiles/rails_7.2.gemfile
|
255
|
+
- gemfiles/rails_8.0.gemfile
|
290
256
|
- lib/acidic_job.rb
|
291
|
-
- lib/acidic_job/
|
257
|
+
- lib/acidic_job/arguments.rb
|
258
|
+
- lib/acidic_job/builder.rb
|
259
|
+
- lib/acidic_job/context.rb
|
260
|
+
- lib/acidic_job/engine.rb
|
292
261
|
- lib/acidic_job/errors.rb
|
293
|
-
- lib/acidic_job/
|
294
|
-
- lib/acidic_job/
|
295
|
-
- lib/acidic_job/
|
296
|
-
- lib/acidic_job/
|
297
|
-
- lib/acidic_job/
|
298
|
-
- lib/acidic_job/idempotency_key.rb
|
299
|
-
- lib/acidic_job/perform_wrapper.rb
|
300
|
-
- lib/acidic_job/recovery_point.rb
|
301
|
-
- lib/acidic_job/rspec_configuration.rb
|
302
|
-
- lib/acidic_job/run.rb
|
303
|
-
- lib/acidic_job/serializer.rb
|
304
|
-
- lib/acidic_job/staging.rb
|
305
|
-
- lib/acidic_job/step.rb
|
306
|
-
- lib/acidic_job/test_case.rb
|
262
|
+
- lib/acidic_job/log_subscriber.rb
|
263
|
+
- lib/acidic_job/serializers/exception_serializer.rb
|
264
|
+
- lib/acidic_job/serializers/job_serializer.rb
|
265
|
+
- lib/acidic_job/serializers/new_record_serializer.rb
|
266
|
+
- lib/acidic_job/serializers/range_serializer.rb
|
307
267
|
- lib/acidic_job/testing.rb
|
308
|
-
- lib/acidic_job/upgrade_service.rb
|
309
268
|
- lib/acidic_job/version.rb
|
310
|
-
- lib/
|
269
|
+
- lib/acidic_job/workflow.rb
|
311
270
|
- lib/generators/acidic_job/install_generator.rb
|
312
|
-
- lib/generators/acidic_job/templates/
|
313
|
-
- lib/generators/acidic_job/templates/drop_acidic_job_keys_migration.rb.erb
|
271
|
+
- lib/generators/acidic_job/templates/create_acidic_job_tables_migration.rb.erb
|
314
272
|
homepage: https://github.com/fractaledmind/acidic_job
|
315
273
|
licenses:
|
316
274
|
- MIT
|
@@ -319,7 +277,6 @@ metadata:
|
|
319
277
|
source_code_uri: https://github.com/fractaledmind/acidic_job
|
320
278
|
changelog_uri: https://github.com/fractaledmind/acidic_job/CHANGELOG.md
|
321
279
|
rubygems_mfa_required: 'true'
|
322
|
-
post_install_message:
|
323
280
|
rdoc_options: []
|
324
281
|
require_paths:
|
325
282
|
- lib
|
@@ -330,12 +287,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
330
287
|
version: 2.7.0
|
331
288
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
332
289
|
requirements:
|
333
|
-
- - "
|
290
|
+
- - ">="
|
334
291
|
- !ruby/object:Gem::Version
|
335
|
-
version:
|
292
|
+
version: '0'
|
336
293
|
requirements: []
|
337
|
-
rubygems_version: 3.3
|
338
|
-
signing_key:
|
294
|
+
rubygems_version: 3.6.3
|
339
295
|
specification_version: 4
|
340
296
|
summary: Idempotent operations for Rails apps, built on top of ActiveJob.
|
341
297
|
test_files: []
|
data/.ruby_version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.7.1
|
data/.tool-versions
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby 3.1.1
|
data/gemfiles/rails_6.1.gemfile
DELETED
data/lib/acidic_job/awaiting.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/concern"
|
4
|
-
|
5
|
-
module AcidicJob
|
6
|
-
module Awaiting
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
def was_awaited_job?
|
12
|
-
(acidic_job_run.present? && acidic_job_run.awaited_by.present?) ||
|
13
|
-
(staged_job_run.present? && staged_job_run.awaited_by.present?)
|
14
|
-
end
|
15
|
-
|
16
|
-
def reenqueue_awaited_by_job
|
17
|
-
run = staged_job_run&.awaited_by || acidic_job_run&.awaited_by
|
18
|
-
|
19
|
-
return unless run
|
20
|
-
return if run.batched_runs.outstanding.any?
|
21
|
-
|
22
|
-
current_step = run.workflow[run.recovery_point.to_s]
|
23
|
-
step_result = run.returning_to
|
24
|
-
|
25
|
-
job = run.job_class.constantize.deserialize(run.serialized_job)
|
26
|
-
# this needs to be explicitly set so that `was_workflow_job?` appropriately returns `true`
|
27
|
-
# which is what the `after_finish :reenqueue_awaited_by_job` check needs
|
28
|
-
job.instance_variable_set(:@acidic_job_run, run)
|
29
|
-
|
30
|
-
# can't reproduce yet, but saw a bug in production where
|
31
|
-
# nested awaits workflows had an unsaved `workflow` attribute
|
32
|
-
run.save! if run.has_changes_to_save?
|
33
|
-
|
34
|
-
step = Step.new(current_step, run, job, step_result)
|
35
|
-
# TODO: WRITE REGRESSION TESTS FOR PARALLEL JOB FAILING AND RETRYING THE ORIGINAL STEP
|
36
|
-
step.progress
|
37
|
-
|
38
|
-
return if run.finished?
|
39
|
-
|
40
|
-
# when a batch of jobs for a step succeeds, we begin processing the `AcidicJob::Run` record again
|
41
|
-
# process_run(run)
|
42
|
-
run.update_column(:locked_at, nil)
|
43
|
-
job.enqueue
|
44
|
-
end
|
45
|
-
|
46
|
-
def enqueue_step_parallel_jobs(jobs_or_jobs_getter, run, step_result)
|
47
|
-
awaited_jobs = case jobs_or_jobs_getter
|
48
|
-
when Array
|
49
|
-
jobs_or_jobs_getter
|
50
|
-
when Symbol, String
|
51
|
-
method(jobs_or_jobs_getter).call
|
52
|
-
end
|
53
|
-
|
54
|
-
AcidicJob::Run.transaction do
|
55
|
-
awaited_jobs.compact.each do |awaited_job|
|
56
|
-
worker_class, args, kwargs = job_args_and_kwargs(awaited_job)
|
57
|
-
|
58
|
-
job = worker_class.new(*args, **kwargs)
|
59
|
-
|
60
|
-
AcidicJob::Run.create!(
|
61
|
-
staged: true,
|
62
|
-
awaited_by: run,
|
63
|
-
job_class: worker_class,
|
64
|
-
serialized_job: job.serialize_job(*args, **kwargs),
|
65
|
-
idempotency_key: job.idempotency_key
|
66
|
-
)
|
67
|
-
run.update(returning_to: step_result)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def step_done(_status, options)
|
73
|
-
run = Run.find(options["run_id"])
|
74
|
-
current_step = run.workflow[run.recovery_point.to_s]
|
75
|
-
# re-hydrate the `step_result` object
|
76
|
-
step_result = YAML.safe_load(options["step_result_yaml"], permitted_classes: [RecoveryPoint, FinishedPoint])
|
77
|
-
step = Step.new(current_step, run, self, step_result)
|
78
|
-
|
79
|
-
# TODO: WRITE REGRESSION TESTS FOR PARALLEL JOB FAILING AND RETRYING THE ORIGINAL STEP
|
80
|
-
step.progress
|
81
|
-
# when a batch of jobs for a step succeeds, we begin processing the `AcidicJob::Run` record again
|
82
|
-
process_run(run)
|
83
|
-
end
|
84
|
-
|
85
|
-
def job_args_and_kwargs(job)
|
86
|
-
case job
|
87
|
-
when Class
|
88
|
-
[job, [], {}]
|
89
|
-
when String
|
90
|
-
[job.constantize, [], {}]
|
91
|
-
when Symbol
|
92
|
-
[job.to_s.constantize, [], {}]
|
93
|
-
else
|
94
|
-
[
|
95
|
-
job.class,
|
96
|
-
job.instance_variable_get(:@__acidic_job_args),
|
97
|
-
job.instance_variable_get(:@__acidic_job_kwargs)
|
98
|
-
]
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/concern"
|
4
|
-
|
5
|
-
module AcidicJob
|
6
|
-
module Extensions
|
7
|
-
module ActionMailer
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
def deliver_acidicly(_options = {})
|
11
|
-
job_class = ::ActionMailer::MailDeliveryJob
|
12
|
-
|
13
|
-
job_args = [@mailer_class.name, @action.to_s, "deliver_now", @params, *@args]
|
14
|
-
# for Sidekiq, this depends on the Sidekiq::Serialization extension
|
15
|
-
serialized_job = job_class.new(job_args).serialize
|
16
|
-
acidic_identifier = job_class.respond_to?(:acidic_identifier) ? job_class.acidic_identifier : :job_id
|
17
|
-
key = IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
|
18
|
-
|
19
|
-
AcidicJob::Run.create!(
|
20
|
-
staged: true,
|
21
|
-
job_class: job_class.name,
|
22
|
-
serialized_job: serialized_job,
|
23
|
-
idempotency_key: key
|
24
|
-
)
|
25
|
-
end
|
26
|
-
alias deliver_transactionally deliver_acidicly
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/concern"
|
4
|
-
|
5
|
-
module AcidicJob
|
6
|
-
module Extensions
|
7
|
-
module ActiveJob
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
concerning :Serialization do
|
11
|
-
class_methods do
|
12
|
-
def serialize_with_arguments(*args, **kwargs)
|
13
|
-
job_or_instantiate(*args, **kwargs).serialize
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def serialize_job(*_args, **_kwargs)
|
18
|
-
serialize
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class_methods do
|
23
|
-
def perform_acidicly(*args, **kwargs)
|
24
|
-
raise UnsupportedExtension unless defined?(::ActiveJob) && self < ::ActiveJob::Base
|
25
|
-
|
26
|
-
serialized_job = serialize_with_arguments(*args, **kwargs)
|
27
|
-
key = IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
|
28
|
-
|
29
|
-
AcidicJob::Run.create!(
|
30
|
-
staged: true,
|
31
|
-
job_class: name,
|
32
|
-
serialized_job: serialized_job,
|
33
|
-
idempotency_key: key
|
34
|
-
)
|
35
|
-
end
|
36
|
-
alias_method :perform_transactionally, :perform_acidicly
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AcidicJob
|
4
|
-
module Extensions
|
5
|
-
module Noticed
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
class_methods do
|
9
|
-
def deliver_acidicly(recipients)
|
10
|
-
new.deliver_acidicly(recipients)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def deliver_acidicly(recipients)
|
15
|
-
# THIS IS A HACK THAT COPIES AND PASTES KEY PARTS OF THE `Noticed::Base` CODE
|
16
|
-
# IN ORDER TO ALLOW US TO TRANSACTIONALLY DELIVER NOTIFICATIONS
|
17
|
-
# THIS IS THUS LIABLE TO BREAK WHENEVER THAT GEM IS UPDATED
|
18
|
-
delivery_methods = self.class.delivery_methods.dup
|
19
|
-
|
20
|
-
Array.wrap(recipients).uniq.each do |recipient|
|
21
|
-
if (index = delivery_methods.find_index { |m| m[:name] == :database })
|
22
|
-
database_delivery_method = delivery_methods.delete_at(index)
|
23
|
-
self.record = run_delivery_method(database_delivery_method,
|
24
|
-
recipient: recipient,
|
25
|
-
enqueue: false,
|
26
|
-
record: nil)
|
27
|
-
end
|
28
|
-
|
29
|
-
delivery_methods.map do |delivery_method|
|
30
|
-
job_class = delivery_method_for(delivery_method[:name], delivery_method[:options])
|
31
|
-
args = {
|
32
|
-
notification_class: self.class.name,
|
33
|
-
options: delivery_method[:options],
|
34
|
-
params: params,
|
35
|
-
recipient: recipient,
|
36
|
-
record: record
|
37
|
-
}
|
38
|
-
serialized_job = job_class.send(:job_or_instantiate, args).serialize
|
39
|
-
acidic_identifier = job_class.respond_to?(:acidic_identifier) ? job_class.acidic_identifier : :job_id
|
40
|
-
key = IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
|
41
|
-
|
42
|
-
AcidicJob::Run.create!(
|
43
|
-
staged: true,
|
44
|
-
job_class: job_class.name,
|
45
|
-
serialized_job: serialized_job,
|
46
|
-
idempotency_key: key
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
alias deliver_transactionally deliver_acidicly
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/concern"
|
4
|
-
require "active_support/callbacks"
|
5
|
-
require "active_support/core_ext/module/concerning"
|
6
|
-
|
7
|
-
module AcidicJob
|
8
|
-
module Extensions
|
9
|
-
module Sidekiq
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
concerning :Serialization do
|
13
|
-
class_methods do
|
14
|
-
# called only from `AcidicJob::Run#enqueue_staged_job`
|
15
|
-
def deserialize(serialized_job_hash)
|
16
|
-
klass = if serialized_job_hash["class"].is_a?(Class)
|
17
|
-
serialized_job_hash["class"]
|
18
|
-
else
|
19
|
-
serialized_job_hash["class"].constantize
|
20
|
-
end
|
21
|
-
worker = klass.new
|
22
|
-
worker.jid = serialized_job_hash["jid"]
|
23
|
-
worker.instance_variable_set(:@args, serialized_job_hash["args"])
|
24
|
-
|
25
|
-
worker
|
26
|
-
end
|
27
|
-
|
28
|
-
# called only from `AcidicJob::PerformAcidicly#perform_acidicly`
|
29
|
-
# and `AcidicJob::DeliverAcidicly#deliver_acidicly`
|
30
|
-
def serialize_with_arguments(args = [], _kwargs = nil)
|
31
|
-
# THIS IS A HACK THAT ESSENTIALLY COPIES THE CODE FROM THE SIDEKIQ CODEBASE TO MIMIC THE BEHAVIOR
|
32
|
-
# updated to handle Sidekiq v6.4.2 at latest
|
33
|
-
args = Array[args]
|
34
|
-
normalized_args = ::Sidekiq.load_json(::Sidekiq.dump_json(args))
|
35
|
-
item = { "class" => self, "args" => normalized_args }
|
36
|
-
dummy_sidekiq_client = ::Sidekiq::Client.new
|
37
|
-
normed = dummy_sidekiq_client.send :normalize_item, item
|
38
|
-
redis_pool = dummy_sidekiq_client.instance_variable_get(:@redis_pool)
|
39
|
-
dummy_sidekiq_client.middleware.invoke(normed["class"], normed, normed["queue"], redis_pool) do
|
40
|
-
normed
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def serialize_job(*args, **kwargs)
|
46
|
-
# `@args` is only set via `deserialize`; it is not a standard Sidekiq thing
|
47
|
-
arguments = args || @args
|
48
|
-
arguments += [kwargs] unless kwargs.empty?
|
49
|
-
normalized_args = ::Sidekiq.load_json(::Sidekiq.dump_json(arguments))
|
50
|
-
item = { "class" => self.class.name, "args" => normalized_args, "jid" => jid }
|
51
|
-
sidekiq_options = sidekiq_options_hash || {}
|
52
|
-
|
53
|
-
sidekiq_options.merge(item)
|
54
|
-
end
|
55
|
-
|
56
|
-
# called only from `AcidicJob::Run#enqueue_staged_job`
|
57
|
-
def enqueue
|
58
|
-
::Sidekiq::Client.push(
|
59
|
-
"class" => self.class,
|
60
|
-
"args" => @args,
|
61
|
-
"jid" => @acidic_job_run&.staged_job_id || @jid
|
62
|
-
)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
concerning :PerformAcidicly do
|
67
|
-
class_methods do
|
68
|
-
def perform_acidicly(*args, **kwargs)
|
69
|
-
serialized_job = serialize_with_arguments(*args, **kwargs)
|
70
|
-
key = IdempotencyKey.new(acidic_identifier).value_for(serialized_job)
|
71
|
-
|
72
|
-
AcidicJob::Run.create!(
|
73
|
-
staged: true,
|
74
|
-
job_class: name,
|
75
|
-
serialized_job: serialized_job,
|
76
|
-
idempotency_key: key
|
77
|
-
)
|
78
|
-
end
|
79
|
-
alias_method :perform_transactionally, :perform_acidicly
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# to balance `perform_async` class method
|
84
|
-
concerning :PerformSync do
|
85
|
-
class_methods do
|
86
|
-
def perform_sync(*args, **kwargs)
|
87
|
-
new.perform(*args, **kwargs)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Following approach used by ActiveJob
|
93
|
-
# https://github.com/rails/rails/blob/93c9534c9871d4adad4bc33b5edc355672b59c61/activejob/lib/active_job/callbacks.rb
|
94
|
-
concerning :Callbacks do
|
95
|
-
class_methods do
|
96
|
-
def around_perform(*filters, &blk)
|
97
|
-
set_callback(:perform, :around, *filters, &blk)
|
98
|
-
end
|
99
|
-
|
100
|
-
def before_perform(*filters, &blk)
|
101
|
-
set_callback(:perform, :before, *filters, &blk)
|
102
|
-
end
|
103
|
-
|
104
|
-
def after_perform(*filters, &blk)
|
105
|
-
set_callback(:perform, :after, *filters, &blk)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Represents an action to set a new API response (which will be stored onto an
|
4
|
-
# idempotency key). One possible option for a return from an #atomic_phase
|
5
|
-
# block.
|
6
|
-
module AcidicJob
|
7
|
-
class FinishedPoint
|
8
|
-
def call(run:)
|
9
|
-
# Skip AR callbacks as there are none on the model
|
10
|
-
run.update_columns(
|
11
|
-
locked_at: nil,
|
12
|
-
recovery_point: Run::FINISHED_RECOVERY_POINT
|
13
|
-
)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|