acidic_job 0.1.1 → 0.1.2

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: 9878e2b82544c04809b49366f27eafcbe28683c39ca877fb99b9649c4bd4dcdd
4
- data.tar.gz: b04206a126a00f84caeb255a6a3bb6542001a6a700345edfd45fe68d39b3fcdd
3
+ metadata.gz: 9681eb2a123d15b96ea8666da752886f1e8365f4be846cef4a2597299378ae37
4
+ data.tar.gz: 83c1a7cafb42e833352f9c919d96d1d2e46e2e22830952dacb468102307f4bc0
5
5
  SHA512:
6
- metadata.gz: 7d7928c276825f884387a6010cf57e1fc2b04f17e657c230c5d6909e8430445dfb903018643812255100ac8fdbf7dfe20fae0f5d194089aa003c7f6b4c996830
7
- data.tar.gz: befa1e96050d612cb42fff983b751f8f04dada4f5ccd5ac81ba0190807f69e6961d1a19bdb6df06bce0e2252c60bac5dd0a37c202afa5c1f03942d46ff469828
6
+ metadata.gz: 1662be5778950bfd429798568aa115c294f992a9dbe530559e9f2f0093f5a767eee5667507f771148ec596a64c78be7a19d55b2965c52a1a94fdc6ae39d3562c
7
+ data.tar.gz: ac8b78d17d4772af7ef4661e4d7aef3b2686c73485e3809ad72dad0ab5cd3c08e630b605a294adcf49f89766ebbbc6b28dd70d0ccbae559afabf3599a744e342
@@ -0,0 +1,18 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.7.1
14
+ - name: Run the default task
15
+ run: |
16
+ gem install bundler -v 2.2.5
17
+ bundle install
18
+ bundle exec rake
data/.gitignore CHANGED
@@ -6,6 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
9
+ .DS_Store
10
+ /test/database.sqlite
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.4
2
+ TargetRubyVersion: 2.7
3
+ NewCops: enable
3
4
 
4
5
  Style/StringLiterals:
5
6
  Enabled: true
data/.ruby_version ADDED
@@ -0,0 +1 @@
1
+ 2.7.1
data/Gemfile CHANGED
@@ -7,6 +7,16 @@ gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
9
 
10
- gem "rspec", "~> 3.0"
10
+ gem "minitest", "~> 5.0"
11
11
 
12
12
  gem "rubocop", "~> 1.7"
13
+
14
+ gem "activerecord", "~> 6.1.3.2"
15
+
16
+ gem "activejob", "~> 6.1.3.2"
17
+
18
+ gem "sqlite3"
19
+
20
+ gem "database_cleaner"
21
+
22
+ gem "simplecov"
data/Gemfile.lock ADDED
@@ -0,0 +1,84 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ acidic_job (0.1.2)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activejob (6.1.3.2)
11
+ activesupport (= 6.1.3.2)
12
+ globalid (>= 0.3.6)
13
+ activemodel (6.1.3.2)
14
+ activesupport (= 6.1.3.2)
15
+ activerecord (6.1.3.2)
16
+ activemodel (= 6.1.3.2)
17
+ activesupport (= 6.1.3.2)
18
+ activesupport (6.1.3.2)
19
+ concurrent-ruby (~> 1.0, >= 1.0.2)
20
+ i18n (>= 1.6, < 2)
21
+ minitest (>= 5.1)
22
+ tzinfo (~> 2.0)
23
+ zeitwerk (~> 2.3)
24
+ ast (2.4.2)
25
+ concurrent-ruby (1.1.9)
26
+ database_cleaner (2.0.1)
27
+ database_cleaner-active_record (~> 2.0.0)
28
+ database_cleaner-active_record (2.0.1)
29
+ activerecord (>= 5.a)
30
+ database_cleaner-core (~> 2.0.0)
31
+ database_cleaner-core (2.0.1)
32
+ docile (1.4.0)
33
+ globalid (0.4.2)
34
+ activesupport (>= 4.2.0)
35
+ i18n (1.8.10)
36
+ concurrent-ruby (~> 1.0)
37
+ minitest (5.14.4)
38
+ parallel (1.20.1)
39
+ parser (3.0.1.1)
40
+ ast (~> 2.4.1)
41
+ rainbow (3.0.0)
42
+ rake (13.0.4)
43
+ regexp_parser (2.1.1)
44
+ rexml (3.2.5)
45
+ rubocop (1.18.3)
46
+ parallel (~> 1.10)
47
+ parser (>= 3.0.0.0)
48
+ rainbow (>= 2.2.2, < 4.0)
49
+ regexp_parser (>= 1.8, < 3.0)
50
+ rexml
51
+ rubocop-ast (>= 1.7.0, < 2.0)
52
+ ruby-progressbar (~> 1.7)
53
+ unicode-display_width (>= 1.4.0, < 3.0)
54
+ rubocop-ast (1.7.0)
55
+ parser (>= 3.0.1.1)
56
+ ruby-progressbar (1.11.0)
57
+ simplecov (0.21.2)
58
+ docile (~> 1.1)
59
+ simplecov-html (~> 0.11)
60
+ simplecov_json_formatter (~> 0.1)
61
+ simplecov-html (0.12.3)
62
+ simplecov_json_formatter (0.1.3)
63
+ sqlite3 (1.4.2)
64
+ tzinfo (2.0.4)
65
+ concurrent-ruby (~> 1.0)
66
+ unicode-display_width (2.0.0)
67
+ zeitwerk (2.4.2)
68
+
69
+ PLATFORMS
70
+ x86_64-darwin-17
71
+
72
+ DEPENDENCIES
73
+ acidic_job!
74
+ activejob (~> 6.1.3.2)
75
+ activerecord (~> 6.1.3.2)
76
+ database_cleaner
77
+ minitest (~> 5.0)
78
+ rake (~> 13.0)
79
+ rubocop (~> 1.7)
80
+ simplecov
81
+ sqlite3
82
+
83
+ BUNDLED WITH
84
+ 2.2.5
data/README.md CHANGED
@@ -26,7 +26,7 @@ TODO: Write usage instructions here
26
26
 
27
27
  ## Development
28
28
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
29
+ 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.
30
30
 
31
31
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
32
 
data/Rakefile CHANGED
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
4
+ require "rake/testtask"
5
5
 
6
- RSpec::Core::RakeTask.new(:spec)
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
7
11
 
8
12
  require "rubocop/rake_task"
9
13
 
10
14
  RuboCop::RakeTask.new
11
15
 
12
- task default: %i[spec rubocop]
16
+ task default: %i[test rubocop]
data/acidic_job.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Idempotent operations for Rails apps, built on top of ActiveJob."
13
13
  spec.homepage = "https://github.com/fractaledmind/acidic_job"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = "https://github.com/fractaledmind/acidic_job"
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency 'activesupport'
30
+ spec.add_dependency "activesupport"
31
31
 
32
32
  # For more information and examples about making a new gem, checkout our
33
33
  # guide at: https://bundler.io/guides/creating_gem.html
data/lib/acidic_job.rb CHANGED
@@ -4,7 +4,9 @@ require_relative "acidic_job/version"
4
4
  require_relative "acidic_job/no_op"
5
5
  require_relative "acidic_job/recovery_point"
6
6
  require_relative "acidic_job/response"
7
+ require "active_support/concern"
7
8
 
9
+ # rubocop:disable Metrics/ModuleLength, Style/Documentation, Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
8
10
  module AcidicJob
9
11
  class IdempotencyKeyRequired < StandardError; end
10
12
 
@@ -26,6 +28,13 @@ module AcidicJob
26
28
 
27
29
  included do
28
30
  attr_reader :key
31
+
32
+ # discard_on MismatchedIdempotencyKeyAndJobArguments
33
+ # discard_on UnknownRecoveryPoint
34
+ # discard_on UnknownAtomicPhaseType
35
+ # discard_on MissingRequiredAttribute
36
+ # retry_on LockedIdempotencyKey
37
+ # retry_on ActiveRecord::SerializationFailure
29
38
  end
30
39
 
31
40
  class_methods do
@@ -52,10 +61,11 @@ module AcidicJob
52
61
  # something like the Shannon entropy equation.
53
62
  IDEMPOTENCY_KEY_MIN_LENGTH = 20
54
63
 
55
- def idempotently(key:, with:) # &block
64
+ # &block
65
+ def idempotently(key:, with:)
56
66
  # set accessors for each argument passed in to ensure they are available
57
67
  # to the step methods the job will have written
58
- set_accessors_for_passed_arguments(with)
68
+ define_accessors_for_passed_arguments(with)
59
69
 
60
70
  validate_passed_idempotency_key(key)
61
71
  validate_passed_arguments(with)
@@ -68,7 +78,7 @@ module AcidicJob
68
78
 
69
79
  # find or create an AcidicJobKey record to store all information about this job
70
80
  # side-effect: will set the @key instance variable
71
- ensure_idempotency_key_record(key, params, defined_steps.first)
81
+ ensure_idempotency_key_record(key, with[:params], defined_steps.first)
72
82
 
73
83
  # if the key record is already marked as finished, immediately return its result
74
84
  return @key.succeeded? if @key.finished?
@@ -109,17 +119,15 @@ module AcidicJob
109
119
  ActiveRecord::Base.transaction(isolation: :read_uncommitted) do
110
120
  phase_result = phase_callable.call
111
121
 
112
- if phase_result.is_a?(NoOp) || phase_result.is_a?(RecoveryPoint) || phase_result.is_a?(Response)
113
- key ||= @key
114
- phase_result.call(key: key)
115
- else
116
- raise UnknownAtomicPhaseType
117
- end
122
+ raise UnknownAtomicPhaseType unless phase_result.is_a?(NoOp) ||
123
+ phase_result.is_a?(RecoveryPoint) ||
124
+ phase_result.is_a?(Response)
125
+
126
+ # TODO: why is this here?
127
+ key ||= @key
128
+ phase_result.call(key: key)
118
129
  end
119
- rescue MismatchedIdempotencyKeyAndJobArguments, LockedIdempotencyKey, UnknownRecoveryPoint, UnknownAtomicPhaseType, MissingRequiredAttribute, ActiveRecord::SerializationFailure => e
120
- error = e
121
- raise e
122
- rescue => e
130
+ rescue StandardError => e
123
131
  error = e
124
132
  raise e
125
133
  ensure
@@ -127,8 +135,8 @@ module AcidicJob
127
135
  # key right away so that another request can try again.
128
136
  if error && !key.nil?
129
137
  begin
130
- key.update(locked_at: nil, error_object: error)
131
- rescue => e
138
+ key.update_columns(locked_at: nil, error_object: error)
139
+ rescue StandardError => e
132
140
  # We're already inside an error condition, so swallow any additional
133
141
  # errors from here and just send them to logs.
134
142
  puts "Failed to unlock key #{key.id} because of #{e}."
@@ -144,21 +152,15 @@ module AcidicJob
144
152
  if @key
145
153
  # Programs enqueuing multiple jobs with different parameters but the
146
154
  # same idempotency key is a bug.
147
- if @key.job_args != params.as_json
148
- raise MismatchedIdempotencyKeyAndJobArguments
149
- end
155
+ raise MismatchedIdempotencyKeyAndJobArguments if @key.job_args != params.as_json
150
156
 
151
157
  # Only acquire a lock if the key is unlocked or its lock has expired
152
158
  # because the original job was long enough ago.
153
- if @key.locked_at && @key.locked_at > Time.current - IDEMPOTENCY_KEY_LOCK_TIMEOUT
154
- raise LockedIdempotencyKey
155
- end
159
+ raise LockedIdempotencyKey if @key.locked_at && @key.locked_at > Time.current - IDEMPOTENCY_KEY_LOCK_TIMEOUT
156
160
 
157
161
  # Lock the key and update latest run unless the job is already
158
162
  # finished.
159
- if !@key.finished?
160
- @key.update!(last_run_at: Time.current, locked_at: Time.current)
161
- end
163
+ @key.update!(last_run_at: Time.current, locked_at: Time.current) unless @key.finished?
162
164
  else
163
165
  @key = AcidicJobKey.create!(
164
166
  idempotency_key: key_val,
@@ -175,9 +177,11 @@ module AcidicJob
175
177
  end
176
178
  end
177
179
 
178
- def set_accessors_for_passed_arguments(passed_arguments)
180
+ def define_accessors_for_passed_arguments(passed_arguments)
179
181
  passed_arguments.each do |accessor, value|
180
- self.class.attr_accessor accessor
182
+ # the reader method may already be defined
183
+ self.class.attr_reader accessor unless respond_to?(accessor)
184
+ # but we should always update the value to match the current value
181
185
  instance_variable_set("@#{accessor}", value)
182
186
  end
183
187
 
@@ -198,7 +202,8 @@ module AcidicJob
198
202
 
199
203
  return if missing_attributes.empty?
200
204
 
201
- raise MissingRequiredAttribute, "The following required job parameters are missing: #{missing_attributes.to_sentence}"
205
+ raise MissingRequiredAttribute,
206
+ "The following required job parameters are missing: #{missing_attributes.to_sentence}"
202
207
  end
203
208
 
204
209
  def define_atomic_phases(defined_steps)
@@ -219,3 +224,4 @@ module AcidicJob
219
224
  end
220
225
  end
221
226
  end
227
+ # rubocop:enable Metrics/ModuleLength, Style/Documentation, Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Represents an action to perform a no-op. One possible option for a return
2
4
  # from an #atomic_phase block.
3
5
  class NoOp
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Represents an action to set a new recovery point. One possible option for a
2
4
  # return from an #atomic_phase block.
3
5
  class RecoveryPoint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Represents an action to set a new API response (which will be stored onto an
2
4
  # idempotency key). One possible option for a return from an #atomic_phase
3
5
  # block.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AcidicJob
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
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: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - fractaledmind
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-20 00:00:00.000000000 Z
11
+ date: 2021-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -31,11 +31,12 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
- - ".circleci/config.yml"
34
+ - ".github/workflows/main.yml"
35
35
  - ".gitignore"
36
- - ".rspec"
37
36
  - ".rubocop.yml"
37
+ - ".ruby_version"
38
38
  - Gemfile
39
+ - Gemfile.lock
39
40
  - LICENSE
40
41
  - README.md
41
42
  - Rakefile
@@ -62,7 +63,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
63
  requirements:
63
64
  - - ">="
64
65
  - !ruby/object:Gem::Version
65
- version: 2.4.0
66
+ version: 2.7.0
66
67
  required_rubygems_version: !ruby/object:Gem::Requirement
67
68
  requirements:
68
69
  - - ">="
data/.circleci/config.yml DELETED
@@ -1,13 +0,0 @@
1
- version: 2.1
2
- jobs:
3
- build:
4
- docker:
5
- - image: ruby:2.7.1
6
- steps:
7
- - checkout
8
- - run:
9
- name: Run the default task
10
- command: |
11
- gem install bundler -v 2.2.5
12
- bundle install
13
- bundle exec rake
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper