acidic_job 1.0.0.pre2 → 1.0.0.pre3

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: 6c10032604b1b559edeb2426cd79e256d904ad15444d139f4f155eee1f01dd11
4
- data.tar.gz: 4dafd1375706fd9a62cd5e0c20e576d2ab5c5ba0d10a1774182ce2dd8a62e615
3
+ metadata.gz: b7c1aec259fa05e5cd62425643534a6944b44df91e1077dfb2eb98fa0717c3e1
4
+ data.tar.gz: 1e9759e91c7a10ea89f39626add3c60b5c3856d54a380958b9f4e6455c6cc937
5
5
  SHA512:
6
- metadata.gz: fd0201a2a905e1c22af8873832bdab15ec08dc233561a978e5282077edb7aeaafd41257cd7be7bc4a64249b1fc41f382f2a1c97ade23e2eb5652a4b3a5687d17
7
- data.tar.gz: 59930dbd34acf5cd52f1ec4b38173a945e2e64b0191c7d5786b863c732091bba44c2f918fd46746c138401b1e2c07228c9d68ff4c406978e431bf8745210fc14
6
+ metadata.gz: 53d61ee2cee38e5e4a136eb37386c2bb912933ba35f839949ac411c486dd14091478d5d23ae3bb2d4ebd3f4c2d9f051e77a64ef1113f8fec2e533f7209662cdd
7
+ data.tar.gz: b8e4dcb13d2f4551d1cc37271003eff592bc03791c77edd3224d306d211c240b850ef258d184155511c29983af349ef9039b4b2dab99d298cc925a36217d7f11
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acidic_job (1.0.0.pre2)
4
+ acidic_job (1.0.0.pre3)
5
5
  activerecord (>= 6.1.0)
6
6
  activesupport
7
7
 
data/UPGRADE_GUIDE.md ADDED
@@ -0,0 +1,71 @@
1
+ # AcidicJob Upgrade Guide
2
+
3
+ 1. Update version requirements in `Gemfile`
4
+
5
+ ```ruby
6
+ -gem "acidic_job"
7
+ +gem "acidic_job", "~> 1.0.0.pre1"
8
+ ```
9
+
10
+ result:
11
+ ```
12
+ Installing acidic_job 1.0.0.pre1 (was 0.7.7)
13
+ Bundle updated!
14
+ ```
15
+
16
+ 2. Generate migration for new `AcidicJob::Run` model
17
+
18
+ ```bash
19
+ rails generate acidic_job
20
+ ```
21
+
22
+ result:
23
+ ```
24
+ create db/migrate/#{yyyymmddhhmmss}_create_acidic_job_runs.rb
25
+ ```
26
+
27
+ 3. Delete any unneeded `AcidicJob::Key` records
28
+
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
+
31
+ For example, this would delete all finished `Key` records over 1 month old:
32
+
33
+ ```ruby
34
+ AcidicJob::Key.where(recovery_point: AcidicJob::Key::RECOVERY_POINT_FINISHED, last_run_at: ..1.month.ago).delete_all
35
+ ```
36
+
37
+ 4. Migrate `AcidicJob::Key` to `AcidicJob::Run`
38
+
39
+ `AcidicJob` ships with an upgrade module that provides a script to migrate older `Key` records to the new `Run` model.
40
+
41
+ ```ruby
42
+ AcidicJob::UpgradeService.execute
43
+ ```
44
+
45
+ This script will prepare an `insert_all` command for `Run` records by mapping the older `Key` data to the new `Run` schema. It also creates the new `Run` records with the same `id` as their `Key` counterparts, and then deletes all `Key` records successfully mapped over. Any `Key` records that were failed to be mapped over will be reported, along with the exception, in the `errored_keys` portion of the resulting hash.
46
+
47
+ result:
48
+ ```
49
+ {
50
+ run_records: <Integer>,
51
+ key_records: <Integer>,
52
+ errored_keys: <Array>
53
+ }
54
+ ```
55
+
56
+ 5. Triage remaining `AcidicJob::Key` records
57
+
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
+
60
+ 6. Ensure all `AcidicJob::Staged` records are processed
61
+
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
+
64
+ 7. Remove the old tables
65
+
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
+
68
+ ```bash
69
+ rails generate acidic_job:drop_tables
70
+ rails db:migrate
71
+ ```
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module AcidicJob
6
+ # recreate the original `Key` model
7
+ class Key < ::ActiveRecord::Base
8
+ RECOVERY_POINT_FINISHED = "FINISHED"
9
+
10
+ self.table_name = "acidic_job_keys"
11
+
12
+ serialize :error_object
13
+ serialize :job_args
14
+ serialize :workflow
15
+ store :attr_accessors
16
+ end
17
+
18
+ # recreate the original `Staged` model
19
+ class Staged < ActiveRecord::Base
20
+ self.table_name = "staged_acidic_jobs"
21
+
22
+ serialize :job_args
23
+
24
+ after_create_commit :enqueue_job
25
+
26
+ private
27
+
28
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
29
+ def enqueue_job
30
+ gid = { "staged_job_gid" => to_global_id.to_s }
31
+
32
+ if job_args.is_a?(Hash) && job_args.key?("arguments")
33
+ job_args["arguments"].concat([gid])
34
+ else
35
+ job_args.concat([gid])
36
+ end
37
+
38
+ case adapter
39
+ when "activejob"
40
+ ::ActiveJob::Base.deserialize(job_args).enqueue
41
+ when "sidekiq"
42
+ job_name.constantize.perform_async(*job_args)
43
+ else
44
+ raise UnknownJobAdapter.new(adapter: adapter)
45
+ end
46
+
47
+ # NOTE: record will be deleted after the job has successfully been performed
48
+ true
49
+ end
50
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
51
+ end
52
+
53
+ module UpgradeService
54
+ def self.execute()
55
+ # prepare an array to hold the attribute hashes to be passed to `insert_all`
56
+ run_attributes = []
57
+ # prepare an array to hold any `Key` records that we couldn't successfully map to `Run` records
58
+ errored_keys = []
59
+
60
+ # iterate over all `AcidicJob::Key` records in batches, preparing a `Run` attribute hash to be passed to `insert_all`
61
+ ::AcidicJob::Key.find_each do |key|
62
+ # map all of the simple attributes directly
63
+ attributes = {
64
+ id: key.id,
65
+ staged: false,
66
+ idempotency_key: key.idempotency_key,
67
+ job_class: key.job_name,
68
+ last_run_at: key.last_run_at,
69
+ locked_at: key.locked_at,
70
+ recovery_point: key.recovery_point,
71
+ error_object: key.error_object,
72
+ attr_accessors: key.attr_accessors,
73
+ workflow: key.workflow,
74
+ created_at: key.created_at,
75
+ updated_at: key.updated_at
76
+ }
77
+
78
+ # prepare the more complicated `job_args` -> `serialized_job` translation
79
+ job_class = key.job_name.constantize
80
+ if defined?(::Sidekiq) && job_class.include?(::Sidekiq::Worker)
81
+ job_class.include(::AcidicJob::Extensions::Sidekiq) unless job_class.include?(::AcidicJob::Extensions::Sidekiq)
82
+ job_instance = job_class.new
83
+ serialized_job = job_instance.serialize_job(*key.job_args)
84
+ elsif defined?(::ActiveJob) && job_class < ::ActiveJob::Base
85
+ job_class.include(::AcidicJob::Extensions::ActiveJob) unless job_class.include?(::AcidicJob::Extensions::ActiveJob)
86
+ job_args = begin
87
+ ::ActiveJob::Arguments.deserialize(key.job_args)
88
+ rescue ::ActiveJob::DeserializationError
89
+ key.job_args
90
+ end
91
+ job_instance = job_class.new(*job_args)
92
+ serialized_job = job_instance.serialize_job()
93
+ end
94
+
95
+ attributes[:serialized_job] = serialized_job
96
+ run_attributes << attributes
97
+ rescue StandardError => exception
98
+ errored_keys << [exception, key]
99
+ end
100
+
101
+ # insert all of the `Run` records
102
+ ::AcidicJob::Run.insert_all(run_attributes)
103
+
104
+ # delete all successfully migrated `Key` record
105
+ ::AcidicJob::Key.where(id: ::AcidicJob::Run.select(:id)).delete_all
106
+
107
+ # return a report of the upgrade migration
108
+ {
109
+ run_records: ::AcidicJob::Run.count,
110
+ key_records: ::AcidicJob::Key.count,
111
+ errored_keys: errored_keys
112
+ }
113
+ end
114
+ end
115
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AcidicJob
4
- VERSION = "1.0.0.pre2"
4
+ VERSION = "1.0.0.pre3"
5
5
  end
data/lib/acidic_job.rb CHANGED
@@ -14,6 +14,7 @@ require_relative "acidic_job/extensions/sidekiq"
14
14
  require_relative "acidic_job/extensions/action_mailer"
15
15
  require_relative "acidic_job/extensions/active_job"
16
16
  require_relative "acidic_job/extensions/noticed"
17
+ require_relative "acidic_job/upgrade_service"
17
18
 
18
19
  require "active_support/concern"
19
20
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module AcidicJob
7
+ module Generators
8
+ class DropTablesGenerator < ActiveRecord::Generators::Base
9
+ source_root File.expand_path("../templates", __dir__)
10
+
11
+ desc "Generates a class for a custom delivery method with the given NAME."
12
+
13
+ # ActiveRecord::Generators::Base inherits from Rails::Generators::NamedBase
14
+ # which requires a NAME parameter for the new table name.
15
+ # Our generator always uses "acidic_job_runs", so we just set a random name here.
16
+ argument :name, type: :string, default: "random_name"
17
+
18
+ # Copies the migration template to db/migrate.
19
+ def copy_acidic_job_runs_migration_files
20
+ migration_template "drop_acidic_job_keys_migration.rb.erb",
21
+ "db/migrate/drop_old_acidic_job_tables.rb"
22
+ end
23
+
24
+ protected
25
+
26
+ def migration_class
27
+ ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -11,16 +11,6 @@ class AcidicJobGenerator < ActiveRecord::Generators::Base
11
11
 
12
12
  source_root File.expand_path("templates", __dir__)
13
13
 
14
- def self.next_migration_number(_path)
15
- if instance_variable_defined?("@prev_migration_nr") # :nocov:
16
- @prev_migration_nr += 1
17
- else
18
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
19
- end
20
-
21
- @prev_migration_nr.to_s
22
- end
23
-
24
14
  # Copies the migration template to db/migrate.
25
15
  def copy_acidic_job_runs_migration_files
26
16
  migration_template "create_acidic_job_runs_migration.rb.erb",
@@ -0,0 +1,27 @@
1
+ class DropOldAcidicJobTables < <%= migration_class %>
2
+ def change
3
+ drop_table :acidic_job_keys do |t|
4
+ t.string :idempotency_key, null: false
5
+ t.string :job_name, null: false
6
+ t.text :job_args, null: true
7
+ t.datetime :last_run_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
8
+ t.datetime :locked_at, null: true
9
+ t.string :recovery_point, null: false
10
+ t.text :error_object
11
+ t.text :attr_accessors
12
+ t.text :workflow
13
+ t.timestamps
14
+
15
+ t.index %i[idempotency_key job_name job_args],
16
+ unique: true,
17
+ name: "idx_acidic_job_keys_on_idempotency_key_n_job_name_n_job_args"
18
+ end
19
+
20
+ drop_table :staged_acidic_jobs do |t|
21
+ t.string :adapter, null: false
22
+ t.string :job_name, null: false
23
+ t.text :job_args, null: true
24
+ t.timestamps
25
+ end
26
+ end
27
+ 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.pre2
4
+ version: 1.0.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - fractaledmind
@@ -68,6 +68,7 @@ files:
68
68
  - LICENSE
69
69
  - README.md
70
70
  - Rakefile
71
+ - UPGRADE_GUIDE.md
71
72
  - acidic_job.gemspec
72
73
  - bin/console
73
74
  - bin/setup
@@ -86,9 +87,12 @@ files:
86
87
  - lib/acidic_job/run.rb
87
88
  - lib/acidic_job/staging.rb
88
89
  - lib/acidic_job/step.rb
90
+ - lib/acidic_job/upgrade_service.rb
89
91
  - lib/acidic_job/version.rb
92
+ - lib/generators/acidic_job/drop_tables_generator.rb
90
93
  - lib/generators/acidic_job_generator.rb
91
94
  - lib/generators/templates/create_acidic_job_runs_migration.rb.erb
95
+ - lib/generators/templates/drop_acidic_job_keys_migration.rb.erb
92
96
  homepage: https://github.com/fractaledmind/acidic_job
93
97
  licenses:
94
98
  - MIT