acidic_job 1.0.0.pre5 → 1.0.0.pre8

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: b8a9a11bcedbc8703e24c32db6474dfe963d8f97120c88c90dc4712026142d61
4
- data.tar.gz: c558f6b90c1044c1320efc018fe4f9886f4af7ebab6a0c1fa8a991232e2b4065
3
+ metadata.gz: 5ed45351f35a4450eebc153e9bff2eba2a8c5cd1dcf5b121f9fa9c9e5e910936
4
+ data.tar.gz: a4eff2b6a54ab1e89fab5b548022e3104540e118694f45bc42ebaf6b8e5cadb1
5
5
  SHA512:
6
- metadata.gz: a9aef4b22eb6ee7860badda470c379d19395c60bc40072085ea3eae6ea140fd77103a07cf142a88310d90f67736300ceb3a755fe3f4283488caf36a7f872baf6
7
- data.tar.gz: 8e1b7d428bc44f83274c3f64454d34c3467e7e701088aee862b71aec55c534a527d7d2e7e7a83fee4a94abe953284a092e8df24b55ae5c7fd195d8df968beb8f
6
+ metadata.gz: 79ebea1341fcab4b84b4534b0a6aa468c1b1b96813bd687744c5caff97050ec62a2af51f6c89b8631801774b06babfb5044233b5e060383051bc33ff4bc8338c
7
+ data.tar.gz: b10c9a7c05c8bd4079a35f865a1c31cef193ccfd2219718cb0df453272211ad2c62772db14763e4244752f6c2c8666a3ef5eb512b07bff7ffa75325d41ccf68e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acidic_job (1.0.0.pre5)
4
+ acidic_job (1.0.0.pre8)
5
5
  activerecord (>= 6.1.0)
6
6
  activesupport
7
7
 
@@ -122,6 +122,8 @@ GEM
122
122
  nokogiri (1.12.3)
123
123
  mini_portile2 (~> 2.6.1)
124
124
  racc (~> 1.4)
125
+ nokogiri (1.12.3-x86_64-darwin)
126
+ racc (~> 1.4)
125
127
  noticed (1.5.7)
126
128
  http (>= 4.0.0)
127
129
  rails (>= 5.2.0)
data/README.md CHANGED
@@ -176,7 +176,6 @@ One final feature for those of you using Sidekiq Pro: an integrated DSL for Side
176
176
  In my opinion, any commercial software using Sidekiq should get Sidekiq Pro; it is _absolutely_ worth the money. If, however, you are using `acidic_job` in a non-commercial application, you could use the open-source dropin replacement for this functionality: https://github.com/breamware/sidekiq-batch
177
177
 
178
178
  ```ruby
179
- # TODO: write code sample
180
179
  class RideCreateJob < ActiveJob::Base
181
180
  include AcidicJob
182
181
 
@@ -192,6 +191,71 @@ class RideCreateJob < ActiveJob::Base
192
191
  end
193
192
  ```
194
193
 
194
+ ## Testing
195
+
196
+ When testing acidic jobs, you are likely to run into `ActiveRecord::TransactionIsolationError`s:
197
+
198
+ ```
199
+ ActiveRecord::TransactionIsolationError: cannot set transaction isolation in a nested transaction
200
+ ```
201
+
202
+ This error is thrown because by default RSpec and most MiniTest test suites use database transactions to keep the test database clean between tests. The database transaction that is wrapping all of the code executed in your test is run at the standard isolation level, but acidic jobs then try to create another transaction run at a more conservative isolation level. You cannot have a nested transaction that runs at a different isolation level, thus, this error.
203
+
204
+ In order to avoid this error, you need to ensure firstly that your tests that run your acidic jobs are not using a database transaction and secondly that they use some different strategy to keep your test database clean. The [DatabaseCleaner](https://github.com/DatabaseCleaner/database_cleaner) gem is a commonly used tool to manage different strategies for keeping your test database clean. As for which strategy to use, `truncation` and `deletion` are both safe, but their speed varies based on our app's table structure (see https://github.com/DatabaseCleaner/database_cleaner#what-strategy-is-fastest). Either is fine; use whichever is faster for your app.
205
+
206
+ In order to make this test setup simpler, `AcidicJob` provides a `TestCase` class that your MiniTest jobs tests can inherit from. It is simple; it inherits from `ActiveJob::TestCase`, sets `use_transactional_tests` to `false`, and ensures `DatabaseCleaner` is run for each of your tests:
207
+
208
+ ```ruby
209
+ class AcidicJob::TestCase < ActiveJob::TestCase
210
+ self.use_transactional_tests = false
211
+
212
+ def before_setup
213
+ super
214
+ DatabaseCleaner.start
215
+ end
216
+
217
+ def after_teardown
218
+ DatabaseCleaner.clean
219
+ super
220
+ end
221
+
222
+ # ...
223
+ end
224
+ ```
225
+
226
+ For those of you using RSpec, you can require the `acidic_job/rspec_configuration` file, which will configure RSpec in the exact same way I have used in my RSpec projects to allow me to test acidic jobs with either the `deletion` strategy but still have all of my other tests use the fast `transaction` strategy:
227
+
228
+ ```ruby
229
+ require "database_cleaner/active_record"
230
+
231
+ # see https://github.com/DatabaseCleaner/database_cleaner#how-to-use
232
+ RSpec.configure do |config|
233
+ config.use_transactional_fixtures = false
234
+
235
+ config.before(:suite) do
236
+ DatabaseCleaner.clean_with :truncation
237
+
238
+ # Here we are defaulting to :transaction but swapping to deletion for some specs;
239
+ # if your spec or its code-under-test uses
240
+ # nested transactions then specify :transactional e.g.:
241
+ # describe "SomeWorker", :transactional do
242
+ #
243
+ DatabaseCleaner.strategy = :transaction
244
+
245
+ config.before(:context, transactional: true) { DatabaseCleaner.strategy = :deletion }
246
+ config.after(:context, transactional: true) { DatabaseCleaner.strategy = :transaction }
247
+ config.before(:context, type: :system) { DatabaseCleaner.strategy = :deletion }
248
+ config.after(:context, type: :system) { DatabaseCleaner.strategy = :transaction }
249
+ end
250
+
251
+ config.around(:each) do |example|
252
+ DatabaseCleaner.cleaning do
253
+ example.run
254
+ end
255
+ end
256
+ end
257
+ ```
258
+
195
259
  ## Development
196
260
 
197
261
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/UPGRADE_GUIDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # AcidicJob Upgrade Guide
2
2
 
3
- 1. Update version requirements in `Gemfile`
3
+ ## 1. Update version requirements in `Gemfile`
4
4
 
5
- ```ruby
6
- -gem "acidic_job"
7
- +gem "acidic_job", "~> 1.0.0.pre1"
5
+ ```diff
6
+ - gem "acidic_job"
7
+ + gem "acidic_job", "~> 1.0.0.pre1"
8
8
  ```
9
9
 
10
10
  result:
@@ -13,7 +13,7 @@ Installing acidic_job 1.0.0.pre4 (was 0.7.7)
13
13
  Bundle updated!
14
14
  ```
15
15
 
16
- 2. Generate migration for new `AcidicJob::Run` model
16
+ ## 2. Generate migration for new `AcidicJob::Run` model
17
17
 
18
18
  ```bash
19
19
  rails generate acidic_job
@@ -24,7 +24,7 @@ result:
24
24
  create db/migrate/#{yyyymmddhhmmss}_create_acidic_job_runs.rb
25
25
  ```
26
26
 
27
- 3. Delete any unneeded `AcidicJob::Key` records
27
+ ## 3. Delete any unneeded `AcidicJob::Key` records
28
28
 
29
29
  Typically, records that are already finished do not need to be retained. Sometimes, however, applications key finished records around for some amount of time for debugging or metrics aggregation. Whatever your application's logic is for whether or not an `AcidicJob::Key` record is still needed, for all unneeded records, delete them.
30
30
 
@@ -34,7 +34,7 @@ For example, this would delete all finished `Key` records over 1 month old:
34
34
  AcidicJob::Key.where(recovery_point: AcidicJob::Key::RECOVERY_POINT_FINISHED, last_run_at: ..1.month.ago).delete_all
35
35
  ```
36
36
 
37
- 4. Migrate `AcidicJob::Key` to `AcidicJob::Run`
37
+ ## 4. Migrate `AcidicJob::Key` to `AcidicJob::Run`
38
38
 
39
39
  `AcidicJob` ships with an upgrade module that provides a script to migrate older `Key` records to the new `Run` model.
40
40
 
@@ -47,21 +47,21 @@ This script will prepare an `insert_all` command for `Run` records by mapping th
47
47
  result:
48
48
  ```
49
49
  {
50
- run_records: <Integer>,
51
- key_records: <Integer>,
52
- errored_keys: <Array>
50
+ run_records: <Integer>,
51
+ key_records: <Integer>,
52
+ errored_keys: <Array>
53
53
  }
54
54
  ```
55
55
 
56
- 5. Triage remaining `AcidicJob::Key` records
56
+ ## 5. Triage remaining `AcidicJob::Key` records
57
57
 
58
58
  If there were any `AcidicJob::Key` records that failed to be mapped to the new `Run` model, you will need to manually triage whatever the exception was. In all likelihood, the exception would be relating to the translation of the `Key#job_args` field to the `Run#serialized_job` field, as all other fields have a fairly straight-forward mapping. If you can't resolve the issue, please open an Issue in GitHub.
59
59
 
60
- 6. Ensure all `AcidicJob::Staged` records are processed
60
+ ## 6. Ensure all `AcidicJob::Staged` records are processed
61
61
 
62
62
  `AcidicJob` still ships with an upgrade module that provides the older `Key` and `Staged` records, so this functionality will still be present to handle any existing records in your database when you deploy the updated version.
63
63
 
64
- 7. Remove the old tables
64
+ ## 7. Remove the old tables
65
65
 
66
66
  Once you have successfully migrated everything over and the new system has been running smoothly for some time, you should drop the old `acidic_job_keys` and `staged_acidic_jobs` tables. We provide a migration generator just for this purpose:
67
67
 
@@ -78,4 +78,4 @@ You can then run the migration to have those tables removed:
78
78
 
79
79
  ```bash
80
80
  rails db:migrate
81
- ```
81
+ ```
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "database_cleaner/active_record"
5
+
6
+ # see https://github.com/DatabaseCleaner/database_cleaner#how-to-use
7
+ RSpec.configure do |config|
8
+ config.use_transactional_fixtures = false
9
+
10
+ config.before(:suite) do
11
+ DatabaseCleaner.clean_with :truncation
12
+
13
+ # Here we are defaulting to :transaction but swapping to deletion for some specs;
14
+ # if your spec or its code-under-test uses
15
+ # nested transactions then specify :transactional e.g.:
16
+ # describe "SomeWorker", :transactional do
17
+ #
18
+ DatabaseCleaner.strategy = :transaction
19
+
20
+ config.before(:context, transactional: true) { DatabaseCleaner.strategy = :deletion }
21
+ config.after(:context, transactional: true) { DatabaseCleaner.strategy = :transaction }
22
+ config.before(:context, type: :system) { DatabaseCleaner.strategy = :deletion }
23
+ config.after(:context, type: :system) { DatabaseCleaner.strategy = :transaction }
24
+ end
25
+
26
+ config.around(:each) do |example|
27
+ DatabaseCleaner.cleaning do
28
+ example.run
29
+ end
30
+ end
31
+ end
@@ -35,6 +35,19 @@ module AcidicJob
35
35
  validates :workflow, presence: true
36
36
  end
37
37
 
38
+ def self.purge
39
+ successfully_completed = where(
40
+ recovery_point: FINISHED_RECOVERY_POINT,
41
+ error_object: nil
42
+ )
43
+ count = successfully_completed.count
44
+
45
+ return 0 if count.zero?
46
+
47
+ Rails.logger.info("Deleting #{count} successfully completed AcidicJob runs")
48
+ successfully_completed.delete_all
49
+ end
50
+
38
51
  def finished?
39
52
  recovery_point == FINISHED_RECOVERY_POINT
40
53
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_job/test_case"
4
+ require "database_cleaner"
5
+
6
+ module AcidicJob
7
+ class TestCase < ActiveJob::TestCase
8
+ self.use_transactional_tests = false if respond_to?(:use_transactional_tests)
9
+
10
+ def before_setup
11
+ @original_cleaners = DatabaseCleaner.cleaners
12
+ DatabaseCleaner.cleaners = transaction_free_cleaners_for(@original_cleaners)
13
+ super
14
+ DatabaseCleaner.start
15
+ end
16
+
17
+ def after_teardown
18
+ DatabaseCleaner.clean
19
+ super
20
+ DatabaseCleaner.cleaners = @original_cleaners
21
+ end
22
+
23
+ private
24
+
25
+ # Ensure that the system's original DatabaseCleaner configuration is maintained, options included,
26
+ # except that any `transaction` strategies for any ORMs are replaced with a `deletion` strategy.
27
+ def transaction_free_cleaners_for(original_cleaners)
28
+ non_transaction_cleaners = original_cleaners.dup.map do |(orm, opts), cleaner|
29
+ [[orm, opts], ensure_no_transaction_strategies_for(cleaner)]
30
+ end.to_h
31
+ DatabaseCleaner::Cleaners.new(non_transaction_cleaners)
32
+ end
33
+
34
+ def ensure_no_transaction_strategies_for(cleaner)
35
+ return cleaner unless strategy_name_for(cleaner) == "transaction"
36
+
37
+ cleaner.strategy = deletion_strategy_for(cleaner)
38
+ cleaner
39
+ end
40
+
41
+ def strategy_name_for(cleaner)
42
+ cleaner # <DatabaseCleaner::Cleaner>
43
+ .strategy # <DatabaseCleaner::ActiveRecord::Truncation>
44
+ .class # DatabaseCleaner::ActiveRecord::Truncation
45
+ .name # "DatabaseCleaner::ActiveRecord::Truncation"
46
+ .rpartition("::") # ["DatabaseCleaner::ActiveRecord", "::", "Truncation"]
47
+ .last # "Truncation"
48
+ .downcase # "truncation"
49
+ end
50
+
51
+ def deletion_strategy_for(cleaner)
52
+ strategy = cleaner.strategy
53
+ strategy_namespace = strategy # <DatabaseCleaner::ActiveRecord::Truncation>
54
+ .class # DatabaseCleaner::ActiveRecord::Truncation
55
+ .name # "DatabaseCleaner::ActiveRecord::Truncation"
56
+ .rpartition("::") # ["DatabaseCleaner::ActiveRecord", "::", "Truncation"]
57
+ .first # "DatabaseCleaner::ActiveRecord"
58
+ deletion_strategy_class_name = [strategy_namespace, "::", "Deletion"].join
59
+ deletion_strategy_class = deletion_strategy_class_name.constantize
60
+ instance_variable_hash = strategy.instance_variables.map do |var|
61
+ [
62
+ var.to_s.remove("@"),
63
+ strategy.instance_variable_get(var)
64
+ ]
65
+ end.to_h
66
+ options = instance_variable_hash.except("db", "connection_class")
67
+
68
+ deletion_strategy_class.new(**options)
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AcidicJob
4
- VERSION = "1.0.0.pre5"
4
+ VERSION = "1.0.0.pre8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acidic_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre5
4
+ version: 1.0.0.pre8
5
5
  platform: ruby
6
6
  authors:
7
7
  - fractaledmind
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-03 00:00:00.000000000 Z
11
+ date: 2022-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -84,9 +84,11 @@ files:
84
84
  - lib/acidic_job/idempotency_key.rb
85
85
  - lib/acidic_job/perform_wrapper.rb
86
86
  - lib/acidic_job/recovery_point.rb
87
+ - lib/acidic_job/rspec_configuration.rb
87
88
  - lib/acidic_job/run.rb
88
89
  - lib/acidic_job/staging.rb
89
90
  - lib/acidic_job/step.rb
91
+ - lib/acidic_job/test_case.rb
90
92
  - lib/acidic_job/upgrade_service.rb
91
93
  - lib/acidic_job/version.rb
92
94
  - lib/generators/acidic_job/drop_tables_generator.rb