acidic_job 1.0.0.rc3 → 1.0.0.rc5

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -6
  3. data/app/models/acidic_job/entry.rb +4 -2
  4. data/app/models/acidic_job/execution.rb +25 -12
  5. data/app/models/acidic_job/value.rb +2 -0
  6. data/lib/acidic_job/builder.rb +2 -2
  7. data/lib/acidic_job/context.rb +36 -20
  8. data/lib/acidic_job/errors.rb +2 -3
  9. data/lib/acidic_job/log_subscriber.rb +4 -6
  10. data/lib/acidic_job/plugin_context.rb +26 -3
  11. data/lib/acidic_job/plugins/transactional_step.rb +4 -4
  12. data/lib/acidic_job/serializer.rb +28 -0
  13. data/lib/acidic_job/serializers/job_serializer.rb +1 -1
  14. data/lib/acidic_job/serializers/range_serializer.rb +1 -3
  15. data/lib/acidic_job/testing.rb +10 -12
  16. data/lib/acidic_job/version.rb +1 -1
  17. data/lib/acidic_job/workflow.rb +44 -32
  18. data/lib/acidic_job.rb +3 -0
  19. data/lib/generators/acidic_job/install_generator.rb +5 -5
  20. data/lib/generators/acidic_job/templates/create_acidic_job_tables_migration.rb.erb +6 -6
  21. metadata +7 -55
  22. data/.codacy.yml +0 -4
  23. data/.github/FUNDING.yml +0 -13
  24. data/.github/workflows/main.yml +0 -38
  25. data/.gitignore +0 -18
  26. data/.rubocop.yml +0 -83
  27. data/.ruby-version +0 -1
  28. data/Gemfile +0 -5
  29. data/Gemfile.lock +0 -201
  30. data/Rakefile +0 -16
  31. data/TODO +0 -77
  32. data/UPGRADE_GUIDE.md +0 -81
  33. data/acidic_job.gemspec +0 -52
  34. data/bin/console +0 -21
  35. data/bin/setup +0 -8
  36. data/bin/test_all +0 -26
  37. data/blog_post.md +0 -28
  38. data/combustion/log/test.log +0 -0
  39. data/gemfiles/rails_7.0.gemfile +0 -11
  40. data/gemfiles/rails_7.1.gemfile +0 -11
  41. data/gemfiles/rails_7.2.gemfile +0 -11
  42. data/gemfiles/rails_8.0.gemfile +0 -11
data/lib/acidic_job.rb CHANGED
@@ -9,6 +9,7 @@ require_relative "acidic_job/arguments"
9
9
  require_relative "acidic_job/plugin_context"
10
10
  require_relative "acidic_job/plugins/transactional_step"
11
11
  require_relative "acidic_job/log_subscriber"
12
+ require_relative "acidic_job/serializer"
12
13
  require_relative "acidic_job/workflow"
13
14
 
14
15
  require "active_support"
@@ -21,6 +22,8 @@ module AcidicJob
21
22
 
22
23
  mattr_accessor :logger, default: DEFAULT_LOGGER
23
24
  mattr_accessor :connects_to
25
+ mattr_accessor :plugins, default: [Plugins::TransactionalStep]
26
+ mattr_accessor :clear_finished_executions_after, default: 1.week
24
27
 
25
28
  def instrument(channel, **options, &block)
26
29
  ActiveSupport::Notifications.instrument("#{channel}.acidic_job", **options.deep_symbolize_keys, &block)
@@ -12,13 +12,13 @@ module AcidicJob
12
12
 
13
13
  # Copies the migration template to db/migrate.
14
14
  def copy_acidic_job_runs_migration_files
15
- migration_template "create_acidic_job_tables_migration.rb.erb",
16
- "db/migrate/create_acidic_job_tables.rb",
17
- migration_version: migration_version
15
+ migration_template(
16
+ "create_acidic_job_tables_migration.rb.erb",
17
+ "db/migrate/create_acidic_job_tables.rb",
18
+ migration_version: migration_version
19
+ )
18
20
  end
19
21
 
20
- protected
21
-
22
22
  def migration_version
23
23
  "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
24
24
  end
@@ -2,30 +2,30 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
2
2
  def change
3
3
  create_table :acidic_job_executions, force: true do |t|
4
4
  t.string :idempotency_key, null: false, index: { unique: true }
5
- t.json :serialized_job, null: false, default: "{}"
5
+ t.json :serialized_job, null: false
6
6
  t.datetime :last_run_at, null: true
7
7
  t.datetime :locked_at, null: true
8
8
  t.string :recover_to, null: true
9
- t.json :definition, null: true, default: "{}"
9
+ t.text :definition, null: true
10
10
 
11
11
  t.timestamps
12
12
  end
13
13
 
14
14
  create_table :acidic_job_entries do |t|
15
- t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions }
15
+ t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions, on_delete: :cascade }
16
16
  t.string :step, null: false
17
17
  t.string :action, null: false
18
18
  t.datetime :timestamp, null: false
19
- t.json :data, null: true, default: "{}"
19
+ t.text :data, null: true
20
20
 
21
21
  t.timestamps
22
22
  end
23
23
  add_index :acidic_job_entries, [:execution_id, :step, :action]
24
24
 
25
25
  create_table :acidic_job_values do |t|
26
- t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions }
26
+ t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions, on_delete: :cascade }
27
27
  t.string :key, null: false
28
- t.json :value, null: false, default: "{}"
28
+ t.text :value, null: false
29
29
 
30
30
  t.timestamps
31
31
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acidic_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc3
4
+ version: 1.0.0.rc5
5
5
  platform: ruby
6
6
  authors:
7
7
  - fractaledmind
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-05-16 00:00:00.000000000 Z
10
+ date: 2025-06-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: json
@@ -97,16 +97,16 @@ dependencies:
97
97
  name: chaotic_job
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ">="
100
+ - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: '0'
102
+ version: 0.3.0
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ">="
107
+ - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: 0.3.0
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: combustion
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -163,34 +163,6 @@ dependencies:
163
163
  - - ">="
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
- - !ruby/object:Gem::Dependency
167
- name: rubocop-minitest
168
- requirement: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- version: '0'
173
- type: :development
174
- prerelease: false
175
- version_requirements: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - ">="
178
- - !ruby/object:Gem::Version
179
- version: '0'
180
- - !ruby/object:Gem::Dependency
181
- name: rubocop-rake
182
- requirement: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- version: '0'
187
- type: :development
188
- prerelease: false
189
- version_requirements: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - ">="
192
- - !ruby/object:Gem::Version
193
- version: '0'
194
166
  - !ruby/object:Gem::Dependency
195
167
  name: simplecov
196
168
  requirement: !ruby/object:Gem::Requirement
@@ -226,33 +198,12 @@ executables: []
226
198
  extensions: []
227
199
  extra_rdoc_files: []
228
200
  files:
229
- - ".codacy.yml"
230
- - ".github/FUNDING.yml"
231
- - ".github/workflows/main.yml"
232
- - ".gitignore"
233
- - ".rubocop.yml"
234
- - ".ruby-version"
235
- - Gemfile
236
- - Gemfile.lock
237
201
  - LICENSE
238
202
  - README.md
239
- - Rakefile
240
- - TODO
241
- - UPGRADE_GUIDE.md
242
- - acidic_job.gemspec
243
203
  - app/models/acidic_job/entry.rb
244
204
  - app/models/acidic_job/execution.rb
245
205
  - app/models/acidic_job/record.rb
246
206
  - app/models/acidic_job/value.rb
247
- - bin/console
248
- - bin/setup
249
- - bin/test_all
250
- - blog_post.md
251
- - combustion/log/test.log
252
- - gemfiles/rails_7.0.gemfile
253
- - gemfiles/rails_7.1.gemfile
254
- - gemfiles/rails_7.2.gemfile
255
- - gemfiles/rails_8.0.gemfile
256
207
  - lib/acidic_job.rb
257
208
  - lib/acidic_job/arguments.rb
258
209
  - lib/acidic_job/builder.rb
@@ -262,6 +213,7 @@ files:
262
213
  - lib/acidic_job/log_subscriber.rb
263
214
  - lib/acidic_job/plugin_context.rb
264
215
  - lib/acidic_job/plugins/transactional_step.rb
216
+ - lib/acidic_job/serializer.rb
265
217
  - lib/acidic_job/serializers/exception_serializer.rb
266
218
  - lib/acidic_job/serializers/job_serializer.rb
267
219
  - lib/acidic_job/serializers/new_record_serializer.rb
data/.codacy.yml DELETED
@@ -1,4 +0,0 @@
1
- ---
2
- exclude_paths:
3
- - "**/*.md"
4
- - "LICENSE"
data/.github/FUNDING.yml DELETED
@@ -1,13 +0,0 @@
1
- # These are supported funding model platforms
2
-
3
- github: fractaledmind
4
- patreon: # Replace with a single Patreon username
5
- open_collective: # Replace with a single Open Collective username
6
- ko_fi: # Replace with a single Ko-fi username
7
- tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8
- community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
- liberapay: # Replace with a single Liberapay username
10
- issuehunt: # Replace with a single IssueHunt username
11
- otechie: # Replace with a single Otechie username
12
- lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13
- custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
@@ -1,38 +0,0 @@
1
- name: CI
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
-
9
- strategy:
10
- fail-fast: false
11
- matrix:
12
- ruby: ["3.0", "3.1", "3.2", "3.3"]
13
- rails: [ "7.1", "7.2", "8.0"]
14
- exclude:
15
- - ruby: "3.0"
16
- rails: "8.0"
17
- - ruby: "3.1"
18
- rails: "8.0"
19
- - ruby: "3.0"
20
- rails: "7.2"
21
-
22
- env:
23
- BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile
24
-
25
- steps:
26
- - uses: actions/checkout@v4
27
-
28
- - name: Set up Ruby
29
- # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
30
- # change this to (see https://github.com/ruby/setup-ruby#versioning):
31
- uses: ruby/setup-ruby@v1
32
- with:
33
- bundler-cache: true # 'bundle install' and cache gems
34
- ruby-version: ${{ matrix.ruby }}
35
-
36
- - name: Run the default task
37
- run: bundle exec rake
38
- timeout-minutes: 2
data/.gitignore DELETED
@@ -1,18 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- .DS_Store
10
- /test/database.sqlite
11
- slides.md
12
- /test/dummy
13
- /test/log
14
- /database.sqlite
15
- /test/combustion/database.sqlite*
16
- /test/combustion/log/test.log
17
- /test/combustion/tmp/*
18
- /gemfiles/*.lock
data/.rubocop.yml DELETED
@@ -1,83 +0,0 @@
1
- require:
2
- - rubocop-minitest
3
- - rubocop-rake
4
-
5
- AllCops:
6
- Exclude:
7
- - inline.rb
8
- - test/simulation.rb
9
- - vendor/bundle/**/*
10
- TargetRubyVersion: 2.7
11
- NewCops: enable
12
-
13
- Style/StringLiterals:
14
- Enabled: true
15
- EnforcedStyle: double_quotes
16
-
17
- Style/StringLiteralsInInterpolation:
18
- Enabled: true
19
- EnforcedStyle: double_quotes
20
-
21
- Layout/LineLength:
22
- Max: 120
23
-
24
- Gemspec/DevelopmentDependencies:
25
- Enabled: false
26
-
27
- Style/Documentation:
28
- Enabled: false
29
-
30
- Metrics/ModuleLength:
31
- Enabled: false
32
-
33
- Metrics/AbcSize:
34
- Enabled: false
35
-
36
- Metrics/MethodLength:
37
- Enabled: false
38
-
39
- Metrics/BlockLength:
40
- Enabled: false
41
-
42
- Metrics/CyclomaticComplexity:
43
- Enabled: false
44
-
45
- Metrics/PerceivedComplexity:
46
- Enabled: false
47
-
48
- Metrics/ClassLength:
49
- Enabled: false
50
-
51
- Minitest/MultipleAssertions:
52
- Enabled: false
53
-
54
- Style/ModuleFunction:
55
- Enabled: false
56
-
57
- Style/RaiseArgs:
58
- EnforcedStyle: compact
59
-
60
- Style/NegatedIf:
61
- Enabled: false
62
-
63
- Style/ClassAndModuleChildren:
64
- Exclude:
65
- - test/**/*_test.rb
66
-
67
- Naming/VariableNumber:
68
- Exclude:
69
- - test/**/*_test.rb
70
-
71
- Style/SingleLineMethods:
72
- Exclude:
73
- - test/**/*_test.rb
74
-
75
- Lint/ConstantDefinitionInBlock:
76
- Exclude:
77
- - test/**/*_test.rb
78
-
79
- Minitest/AssertTruthy:
80
- Enabled: false
81
-
82
- Minitest/RefuteFalse:
83
- Enabled: false
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- ruby-3.3.4
data/Gemfile DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- gemspec
data/Gemfile.lock DELETED
@@ -1,201 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- acidic_job (1.0.0.rc3)
5
- activejob (>= 7.1)
6
- activerecord (>= 7.1)
7
- activesupport (>= 7.1)
8
- json (>= 2.7.0)
9
- railties (>= 7.1)
10
-
11
- GEM
12
- remote: https://rubygems.org/
13
- specs:
14
- actionmailer (7.2.1.1)
15
- actionpack (= 7.2.1.1)
16
- actionview (= 7.2.1.1)
17
- activejob (= 7.2.1.1)
18
- activesupport (= 7.2.1.1)
19
- mail (>= 2.8.0)
20
- rails-dom-testing (~> 2.2)
21
- actionpack (7.2.1.1)
22
- actionview (= 7.2.1.1)
23
- activesupport (= 7.2.1.1)
24
- nokogiri (>= 1.8.5)
25
- racc
26
- rack (>= 2.2.4, < 3.2)
27
- rack-session (>= 1.0.1)
28
- rack-test (>= 0.6.3)
29
- rails-dom-testing (~> 2.2)
30
- rails-html-sanitizer (~> 1.6)
31
- useragent (~> 0.16)
32
- actionview (7.2.1.1)
33
- activesupport (= 7.2.1.1)
34
- builder (~> 3.1)
35
- erubi (~> 1.11)
36
- rails-dom-testing (~> 2.2)
37
- rails-html-sanitizer (~> 1.6)
38
- activejob (7.2.1.1)
39
- activesupport (= 7.2.1.1)
40
- globalid (>= 0.3.6)
41
- activemodel (7.2.1.1)
42
- activesupport (= 7.2.1.1)
43
- activerecord (7.2.1.1)
44
- activemodel (= 7.2.1.1)
45
- activesupport (= 7.2.1.1)
46
- timeout (>= 0.4.0)
47
- activesupport (7.2.1.1)
48
- base64
49
- bigdecimal
50
- concurrent-ruby (~> 1.0, >= 1.3.1)
51
- connection_pool (>= 2.2.5)
52
- drb
53
- i18n (>= 1.6, < 2)
54
- logger (>= 1.4.2)
55
- minitest (>= 5.1)
56
- securerandom (>= 0.3)
57
- tzinfo (~> 2.0, >= 2.0.5)
58
- ast (2.4.2)
59
- base64 (0.2.0)
60
- bigdecimal (3.1.8)
61
- builder (3.3.0)
62
- chaotic_job (0.3.0)
63
- combustion (1.3.7)
64
- activesupport (>= 3.0.0)
65
- railties (>= 3.0.0)
66
- thor (>= 0.14.6)
67
- concurrent-ruby (1.3.4)
68
- connection_pool (2.4.0)
69
- crass (1.0.6)
70
- date (3.4.1)
71
- docile (1.4.0)
72
- drb (2.2.1)
73
- erubi (1.13.0)
74
- globalid (1.2.1)
75
- activesupport (>= 6.1)
76
- i18n (1.14.6)
77
- concurrent-ruby (~> 1.0)
78
- io-console (0.7.2)
79
- irb (1.14.1)
80
- rdoc (>= 4.0.0)
81
- reline (>= 0.4.2)
82
- json (2.10.2)
83
- logger (1.6.1)
84
- loofah (2.22.0)
85
- crass (~> 1.0.2)
86
- nokogiri (>= 1.12.0)
87
- mail (2.8.1)
88
- mini_mime (>= 0.1.1)
89
- net-imap
90
- net-pop
91
- net-smtp
92
- mini_mime (1.1.5)
93
- mini_portile2 (2.8.7)
94
- minitest (5.25.1)
95
- net-imap (0.5.1)
96
- date
97
- net-protocol
98
- net-pop (0.1.2)
99
- net-protocol
100
- net-protocol (0.2.2)
101
- timeout
102
- net-smtp (0.5.0)
103
- net-protocol
104
- nokogiri (1.16.7)
105
- mini_portile2 (~> 2.8.2)
106
- racc (~> 1.4)
107
- nokogiri (1.16.7-x86_64-darwin)
108
- racc (~> 1.4)
109
- parallel (1.22.1)
110
- parser (3.2.2.0)
111
- ast (~> 2.4.1)
112
- psych (5.1.2)
113
- stringio
114
- racc (1.8.1)
115
- rack (3.1.8)
116
- rack-session (2.0.0)
117
- rack (>= 3.0.0)
118
- rack-test (2.1.0)
119
- rack (>= 1.3)
120
- rackup (2.1.0)
121
- rack (>= 3)
122
- webrick (~> 1.8)
123
- rails-dom-testing (2.2.0)
124
- activesupport (>= 5.0.0)
125
- minitest
126
- nokogiri (>= 1.6)
127
- rails-html-sanitizer (1.6.0)
128
- loofah (~> 2.21)
129
- nokogiri (~> 1.14)
130
- railties (7.2.1.1)
131
- actionpack (= 7.2.1.1)
132
- activesupport (= 7.2.1.1)
133
- irb (~> 1.13)
134
- rackup (>= 1.0.0)
135
- rake (>= 12.2)
136
- thor (~> 1.0, >= 1.2.2)
137
- zeitwerk (~> 2.6)
138
- rainbow (3.1.1)
139
- rake (13.2.1)
140
- rdoc (6.7.0)
141
- psych (>= 4.0.0)
142
- regexp_parser (2.8.0)
143
- reline (0.5.10)
144
- io-console (~> 0.5)
145
- rexml (3.2.5)
146
- rubocop (1.50.2)
147
- json (~> 2.3)
148
- parallel (~> 1.10)
149
- parser (>= 3.2.0.0)
150
- rainbow (>= 2.2.2, < 4.0)
151
- regexp_parser (>= 1.8, < 3.0)
152
- rexml (>= 3.2.5, < 4.0)
153
- rubocop-ast (>= 1.28.0, < 2.0)
154
- ruby-progressbar (~> 1.7)
155
- unicode-display_width (>= 2.4.0, < 3.0)
156
- rubocop-ast (1.28.0)
157
- parser (>= 3.2.1.0)
158
- rubocop-minitest (0.30.0)
159
- rubocop (>= 1.39, < 2.0)
160
- rubocop-rake (0.6.0)
161
- rubocop (~> 1.0)
162
- ruby-progressbar (1.13.0)
163
- securerandom (0.3.1)
164
- simplecov (0.22.0)
165
- docile (~> 1.1)
166
- simplecov-html (~> 0.11)
167
- simplecov_json_formatter (~> 0.1)
168
- simplecov-html (0.12.3)
169
- simplecov_json_formatter (0.1.4)
170
- sqlite3 (1.6.2)
171
- mini_portile2 (~> 2.8.0)
172
- sqlite3 (1.6.2-x86_64-darwin)
173
- stringio (3.1.1)
174
- thor (1.3.2)
175
- timeout (0.4.1)
176
- tzinfo (2.0.6)
177
- concurrent-ruby (~> 1.0)
178
- unicode-display_width (2.4.2)
179
- useragent (0.16.10)
180
- webrick (1.8.2)
181
- zeitwerk (2.7.1)
182
-
183
- PLATFORMS
184
- ruby
185
- x86_64-darwin-17
186
-
187
- DEPENDENCIES
188
- acidic_job!
189
- actionmailer (>= 7.1)
190
- chaotic_job
191
- combustion
192
- minitest
193
- rake
194
- rubocop
195
- rubocop-minitest
196
- rubocop-rake
197
- simplecov
198
- sqlite3
199
-
200
- BUNDLED WITH
201
- 2.5.21
data/Rakefile DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rake/testtask"
5
-
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
9
- t.test_files = FileList["test/**/*_test.rb"]
10
- end
11
-
12
- require "rubocop/rake_task"
13
-
14
- RuboCop::RakeTask.new
15
-
16
- task default: %i[test rubocop]
data/TODO DELETED
@@ -1,77 +0,0 @@
1
- - [x] Track number of runs per execution (resolves #79)
2
- This is accomplished with the new `entries` table, as proven by the `idempotency_check` feature, which only runs on a retry.
3
-
4
- - [x] Store errors with more context and without full error history (resolves #80)
5
- This is also accomplished with the new `entries` table, by storing a separate error entry for any raised errors.
6
-
7
- - [x] All traversal over a collection added to the context within the workflow (resolves #81)
8
- The new collection traversal logic resolves #81, as proven by the test case. You can traverse a key for a context value. For example,
9
- ```ruby
10
- execute :prepare_collection
11
- traverse :collection, using: :process_item
12
-
13
- def prepare_collection = @ctx[:collection] = 1..5
14
- def process_item(item) = @processed_items << item
15
- ```
16
-
17
- - [x] Handle case where non-idempotent external write succeeds but recording fails (resolves #82)
18
- The new `idempotency_check` option accomplishes this, by allowing a step making external IO to define a method that checks if the write was already successfully made when re-running a step in a retry.
19
-
20
- - [x] Ensure any and all exceptions can be serialized and deserialized (resolves #83)
21
- The original serializer was too naive and couldn't deserialize, for example, an `ActionView::Template::Error` which requires that `$!` be set when initializing the object.
22
-
23
- The new `ExceptionSerializer` uses Ruby's built-in YAML encoding of exceptions to serialize and deserialize the objects, laying on Zlib to ensure compact byte storage.
24
-
25
- - [x] Handle duplicate workflow step names (resolves #87)
26
- Adding a `DuplicateStepError` exception raised when building the workflow definition resolved this issue.
27
-
28
- - [ ] Add a `context` step type (resolves #89)
29
- Use case: the workflow may or may not have the data it needs to proceed. If it doesn't, it should make an API call to fetch the data. The API call may take a while, so we should be able to handle that as well.
30
-
31
- Example usage:
32
- ```ruby
33
- context :slack_author, fallback: :fetch_slack_author
34
-
35
- def slack_author
36
- Slack::Profile.find_by(uid: @user_uid)
37
- end
38
-
39
- def fetch_slack_author
40
- api_response = Slack::Client.new().get_user(uid: @user_uid)
41
- if api_response[:ok]
42
- [Slack::ProcessProfileSlackJob.new(@installation, api_response[:user])]
43
- else
44
- raise DoNotRetryJob
45
- end
46
- end
47
- ```
48
-
49
- Psuedo code for implementation:
50
- ```ruby
51
- result = resolve_method(primary_method_name).call
52
- if result
53
- @ctx[primary_method_name] = result
54
- else
55
- fallback = resolve_method(fallback_method_name).call
56
- case fallback
57
- in ActiveJob::Base then awaits(fallback)
58
- in Array[ActiveJob::Base] then awaits(fallback)
59
- else @ctx[primary_method_name] = result
60
- end
61
- end
62
- ```
63
-
64
- - [ ] Add documentation on how to "migrate" a workflow (resolves #90)
65
- The v1 alpha already includes a check that the persisted workflow definition matches the job's current definition. This ensures that no job tries to run with an outdated definition. However, we should document the proper way to update a workflow definition.
66
-
67
- The process can only be additive, like a strong migration. First, you create a new job with a new name that is a clone of the original job. Make the necessary changes to the new job. Update your codebase to only enqueue the new job. Deploy this change, where both the new job and the old jobs exist, but the application only enqueues the new job. Once deployed, wait until all currently running instances of the old job complete (provide some docs on how to check this). Once all old job instances are complete, you can safely delete the old job and deploy that change. This process ensures that no job is running with an outdated definition.
68
-
69
- - [ ] Automatically retry the serializable transaction for find/create the Run record (resolves #91)
70
- Serializable transactions are prone to failure: https://stackoverflow.com/a/21715207/2884386
71
-
72
- Currently, if the transaction fails, the job will fail. We need to build automatic retries into the gem, as this failure will naturally resolve. But, we should also add a limit to the number of retries to prevent infinite loops.
73
-
74
- - [ ] Ensure the gem works with GoodJob (resolves #92 and #94)
75
- In the current version, GoodJob can't handle messing with the `job_id` and retrying a failed job raises a NoMethodError: "undefined method `utc' for an instance of Float".
76
-
77
- - [ ] Ensure users can transactionally enqueue other entities, like ActionMailer or Noticed objects