acidic_job 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +6 -1
- data/acidic_job.gemspec +10 -10
- data/lib/acidic_job/version.rb +1 -1
- data/lib/acidic_job.rb +11 -9
- data/lib/generators/acidic_job_generator.rb +8 -7
- data/lib/generators/templates/migration.rb +3 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 528d362023c8d2547054566f13d65556e057285124ffb05f8bc4c6007848b5cb
|
4
|
+
data.tar.gz: 05d08959ff8b674b48966ce4b879fd8c290d658a20c24b6af27e0c1fa8150452
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68bdc77c5e23e4fa680ca9ec72e00cf62cc1bcb2fc133b539d4c17f68b8926da9edd19f895ff92a0a379db567aee9ee949f0ade58eee0ef8b38edd61d28b5c19
|
7
|
+
data.tar.gz: b352b70b51cf7f3244a057dc5d6b2a89ede6e9b317346dd0fd0d54e9115ffff84a86670ac27c3bd45dc8b8f28d535de9af308fbd1b6be8dbd6eec76a7d740485
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
acidic_job (0.
|
4
|
+
acidic_job (0.3.0)
|
5
5
|
activerecord (>= 4.0.0)
|
6
6
|
activesupport
|
7
7
|
|
@@ -37,6 +37,7 @@ GEM
|
|
37
37
|
zeitwerk (~> 2.3)
|
38
38
|
ast (2.4.2)
|
39
39
|
builder (3.2.4)
|
40
|
+
coderay (1.1.3)
|
40
41
|
concurrent-ruby (1.1.9)
|
41
42
|
crass (1.0.6)
|
42
43
|
database_cleaner (2.0.1)
|
@@ -65,6 +66,9 @@ GEM
|
|
65
66
|
parallel (1.20.1)
|
66
67
|
parser (3.0.1.1)
|
67
68
|
ast (~> 2.4.1)
|
69
|
+
pry (0.14.1)
|
70
|
+
coderay (~> 1.1)
|
71
|
+
method_source (~> 1.0)
|
68
72
|
racc (1.5.2)
|
69
73
|
rack (2.2.3)
|
70
74
|
rack-test (1.1.0)
|
@@ -123,6 +127,7 @@ DEPENDENCIES
|
|
123
127
|
activerecord (~> 6.1.3.2)
|
124
128
|
database_cleaner
|
125
129
|
minitest (~> 5.0)
|
130
|
+
pry
|
126
131
|
railties (>= 4.0)
|
127
132
|
rake (~> 13.0)
|
128
133
|
rubocop (~> 1.7)
|
data/acidic_job.gemspec
CHANGED
@@ -3,15 +3,15 @@
|
|
3
3
|
require_relative "lib/acidic_job/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name
|
7
|
-
spec.version
|
8
|
-
spec.authors
|
9
|
-
spec.email
|
6
|
+
spec.name = "acidic_job"
|
7
|
+
spec.version = AcidicJob::VERSION
|
8
|
+
spec.authors = ["fractaledmind"]
|
9
|
+
spec.email = ["stephen.margheim@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary
|
12
|
-
spec.description
|
13
|
-
spec.homepage
|
14
|
-
spec.license
|
11
|
+
spec.summary = "Idempotent operations for Rails apps, built on top of ActiveJob."
|
12
|
+
spec.description = "Idempotent operations for Rails apps, built on top of ActiveJob."
|
13
|
+
spec.homepage = "https://github.com/fractaledmind/acidic_job"
|
14
|
+
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -23,8 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
24
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
25
25
|
end
|
26
|
-
spec.bindir
|
27
|
-
spec.executables
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
30
|
spec.add_dependency "activesupport"
|
data/lib/acidic_job/version.rb
CHANGED
data/lib/acidic_job.rb
CHANGED
@@ -24,10 +24,11 @@ module AcidicJob
|
|
24
24
|
self.table_name = "acidic_job_keys"
|
25
25
|
|
26
26
|
serialize :error_object
|
27
|
+
serialize :job_args
|
27
28
|
|
29
|
+
validates :idempotency_key, presence: true, uniqueness: {scope: [:job_name, :job_args]}
|
28
30
|
validates :job_name, presence: true
|
29
31
|
validates :job_args, presence: true
|
30
|
-
validates :idempotency_key, presence: true
|
31
32
|
validates :last_run_at, presence: true
|
32
33
|
validates :recovery_point, presence: true
|
33
34
|
|
@@ -84,7 +85,7 @@ module AcidicJob
|
|
84
85
|
# close proximity, one of the two will be aborted by Postgres because we're
|
85
86
|
# using a transaction with SERIALIZABLE isolation level. It may not look
|
86
87
|
# it, but this code is safe from races.
|
87
|
-
ensure_idempotency_key_record(job_id,
|
88
|
+
ensure_idempotency_key_record(job_id, defined_steps.first)
|
88
89
|
|
89
90
|
# if the key record is already marked as finished, immediately return its result
|
90
91
|
return @key.succeeded? if @key.finished?
|
@@ -126,7 +127,7 @@ module AcidicJob
|
|
126
127
|
|
127
128
|
phase_result.call(key: key)
|
128
129
|
end
|
129
|
-
rescue
|
130
|
+
rescue => e
|
130
131
|
error = e
|
131
132
|
raise e
|
132
133
|
ensure
|
@@ -134,7 +135,7 @@ module AcidicJob
|
|
134
135
|
# key right away so that another request can try again.
|
135
136
|
begin
|
136
137
|
key.update_columns(locked_at: nil, error_object: error) if error.present?
|
137
|
-
rescue
|
138
|
+
rescue => e
|
138
139
|
# We're already inside an error condition, so swallow any additional
|
139
140
|
# errors from here and just send them to logs.
|
140
141
|
puts "Failed to unlock key #{key.id} because of #{e}."
|
@@ -142,13 +143,14 @@ module AcidicJob
|
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
145
|
-
def ensure_idempotency_key_record(key_val,
|
146
|
+
def ensure_idempotency_key_record(key_val, first_step)
|
146
147
|
isolation_level = case ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
147
148
|
when :sqlite
|
148
149
|
:read_uncommitted
|
149
150
|
else
|
150
151
|
:serializable
|
151
|
-
|
152
|
+
end
|
153
|
+
serialized_job_info = serialize
|
152
154
|
|
153
155
|
ActiveRecord::Base.transaction(isolation: isolation_level) do
|
154
156
|
@key = Key.find_by(idempotency_key: key_val)
|
@@ -156,7 +158,7 @@ module AcidicJob
|
|
156
158
|
if @key
|
157
159
|
# Programs enqueuing multiple jobs with different parameters but the
|
158
160
|
# same idempotency key is a bug.
|
159
|
-
raise MismatchedIdempotencyKeyAndJobArguments if @key.job_args !=
|
161
|
+
raise MismatchedIdempotencyKeyAndJobArguments if @key.job_args != serialized_job_info["arguments"]
|
160
162
|
|
161
163
|
# Only acquire a lock if the key is unlocked or its lock has expired
|
162
164
|
# because the original job was long enough ago.
|
@@ -170,8 +172,8 @@ module AcidicJob
|
|
170
172
|
locked_at: Time.current,
|
171
173
|
last_run_at: Time.current,
|
172
174
|
recovery_point: first_step,
|
173
|
-
job_name:
|
174
|
-
job_args:
|
175
|
+
job_name: serialized_job_info["job_class"],
|
176
|
+
job_args: serialized_job_info["arguments"]
|
175
177
|
)
|
176
178
|
end
|
177
179
|
end
|
@@ -23,15 +23,16 @@ class AcidicJobGenerator < ActiveRecord::Generators::Base
|
|
23
23
|
# Copies the migration template to db/migrate.
|
24
24
|
def copy_files
|
25
25
|
migration_template "migration.rb",
|
26
|
-
|
26
|
+
"db/migrate/create_acidic_job_keys.rb"
|
27
27
|
end
|
28
28
|
|
29
29
|
protected
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
|
31
|
+
def migration_class
|
32
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
33
|
+
ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
|
34
|
+
else
|
35
|
+
ActiveRecord::Migration
|
36
36
|
end
|
37
|
+
end
|
37
38
|
end
|
@@ -10,8 +10,9 @@ class CreateAcidicJobKeys < <%= migration_class %>
|
|
10
10
|
t.text :error_object
|
11
11
|
t.timestamps
|
12
12
|
|
13
|
-
t.index %i[idempotency_key job_name job_args],
|
14
|
-
|
13
|
+
t.index %i[idempotency_key job_name job_args],
|
14
|
+
unique: true,
|
15
|
+
name: "idx_acidic_job_keys_on_idempotency_key_n_job_name_n_job_args"
|
15
16
|
end
|
16
17
|
end
|
17
18
|
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: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fractaledmind
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-08-
|
11
|
+
date: 2021-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|