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 +4 -4
- data/Gemfile.lock +1 -1
- data/UPGRADE_GUIDE.md +71 -0
- data/lib/acidic_job/upgrade_service.rb +115 -0
- data/lib/acidic_job/version.rb +1 -1
- data/lib/acidic_job.rb +1 -0
- data/lib/generators/acidic_job/drop_tables_generator.rb +31 -0
- data/lib/generators/acidic_job_generator.rb +0 -10
- data/lib/generators/templates/drop_acidic_job_keys_migration.rb.erb +27 -0
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7c1aec259fa05e5cd62425643534a6944b44df91e1077dfb2eb98fa0717c3e1
|
4
|
+
data.tar.gz: 1e9759e91c7a10ea89f39626add3c60b5c3856d54a380958b9f4e6455c6cc937
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53d61ee2cee38e5e4a136eb37386c2bb912933ba35f839949ac411c486dd14091478d5d23ae3bb2d4ebd3f4c2d9f051e77a64ef1113f8fec2e533f7209662cdd
|
7
|
+
data.tar.gz: b8e4dcb13d2f4551d1cc37271003eff592bc03791c77edd3224d306d211c240b850ef258d184155511c29983af349ef9039b4b2dab99d298cc925a36217d7f11
|
data/Gemfile.lock
CHANGED
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
|
data/lib/acidic_job/version.rb
CHANGED
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.
|
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
|