dalliance 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33f7433a3391650bd85c64aa0168d2ba9c47a58623fb939241f5d379f9fd621e
4
- data.tar.gz: f0cd58c87d0c512592ca19ea3f25d572569302a1e2c2fb4c8a0864ac2827a9d5
3
+ metadata.gz: bfda33ea2cc9d97c6896fbab7cfb6d3c644ce56c64f22632c5e744544770a853
4
+ data.tar.gz: cdd5a93b644a426edc9a4007ef65c373aebe6fe9aac7b30f3096a47fdfaa11e6
5
5
  SHA512:
6
- metadata.gz: 6882e52916979a54c75a589ead81bb4a20b2639129ae18751afc11c45ccd6e1ddd2c2eee0ecb43ed9901c0ebd9d4e194621321c7d8e2474ec69c804d4e6c7884
7
- data.tar.gz: c1e5741fdcfcb3914d8b729476a7e12c64305125abb94a10687dd79693ef5499d0c61467b466e387dc3a60fd62e56354e97e17ce1f7f38d63cdc94ba76d69aa0
6
+ metadata.gz: 674870bb0d8db5f0baf0cd27f7475cda00de7fd5a8b3d5b37c96ec6c008f127377b6e4ed8519d24ef6792d8ec74a4660ca85310e89594cfbb477085710c6a2d7
7
+ data.tar.gz: 4227f25b65186249d137ccd242df99adf6bd70a4b3993799c79a60bbb57d7bca799e7236de219da44cb8539e3bc73ffbbea3fc197eaf37caeb136341bf98844d
@@ -0,0 +1,107 @@
1
+ version: 2.1
2
+
3
+ defaults: &defaults
4
+ working_directory: ~/app
5
+ docker:
6
+ - image: circleci/ruby:2.6.5
7
+ - image: redis
8
+ # - image: circleci/mysql:5.7
9
+ # environment:
10
+ # MYSQL_USER: root
11
+ # MYSQL_PASSWORD: ''
12
+
13
+ jobs:
14
+ build:
15
+ <<: *defaults
16
+ parallelism: 1
17
+ steps:
18
+ - checkout
19
+
20
+
21
+ - restore_cache:
22
+ keys:
23
+ - v2-bundle-{{ checksum "Gemfile.lock" }}
24
+ - run:
25
+ name: Bundle install
26
+ command: bundle check || bundle install --retry=3 --path vendor/bundle
27
+ - save_cache:
28
+ key: v2-bundle-{{ checksum "Gemfile.lock" }}
29
+ paths:
30
+ - vendor/bundle
31
+ - persist_to_workspace:
32
+ root: ~/
33
+ paths:
34
+ - app
35
+
36
+ test:
37
+ <<: *defaults
38
+ parallelism: 1
39
+ steps:
40
+ - attach_workspace:
41
+ at: ~/
42
+
43
+ - run: bundle --path vendor/bundle
44
+
45
+ # - run:
46
+ # name: Wait for DB
47
+ # command: dockerize -wait tcp://localhost:3306 -timeout 1m
48
+
49
+ - run:
50
+ name: Run RSpec tests
51
+ command: |
52
+ TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
53
+ echo $TEST_FILES
54
+ bundle exec rspec --profile 10 \
55
+ --format RspecJunitFormatter \
56
+ --out test_results/rspec.xml \
57
+ --format progress \
58
+ $TEST_FILES
59
+ - store_test_results:
60
+ path: test_results
61
+ - store_artifacts:
62
+ path: test_results
63
+
64
+ bundler_audit:
65
+ <<: *defaults
66
+ parallelism: 1
67
+ steps:
68
+ - attach_workspace:
69
+ at: ~/
70
+ - run: bundle --path vendor/bundle
71
+ - run:
72
+ name: Run bundler-audit
73
+ command: |
74
+ if [[ "${CIRCLE_NODE_INDEX}" == 0 ]]
75
+ then
76
+ bundle exec bundle-audit update && bundle exec bundle-audit check
77
+ fi
78
+
79
+ rubocop:
80
+ <<: *defaults
81
+ parallelism: 1
82
+ steps:
83
+ - attach_workspace:
84
+ at: ~/
85
+ - run: bundle --path vendor/bundle
86
+ - run:
87
+ name: Run rubocop
88
+ command: |
89
+ if [[ "${CIRCLE_NODE_INDEX}" == 0 ]]
90
+ then
91
+ bundle exec rubocop -D -l
92
+ fi
93
+
94
+ workflows:
95
+ version: 2
96
+ continuous_integration:
97
+ jobs:
98
+ - build
99
+ - test:
100
+ requires:
101
+ - build
102
+ - bundler_audit:
103
+ requires:
104
+ - build
105
+ - rubocop:
106
+ requires:
107
+ - build
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in dalliance.gemspec
4
4
  gemspec
@@ -19,7 +19,19 @@ In your model:
19
19
  process_method is the name of the method to invoke for background processing
20
20
  to kick it off just call dalliance_background_process
21
21
 
22
- Handle your migrations:
22
+ Models can also be re-processed to allow front-end users to reprocess without
23
+ needing to loop in PMs or developers:
24
+
25
+ class Model < ActiveRecord::Base
26
+ dalliance :process_method,
27
+ reprocess_method: :reprocessing_method
28
+ end
29
+
30
+ Keep in mind that a record that has not already been completely processed (eg in
31
+ a state of 'pending' or 'processing') cannot be reprocessed. Attempting to
32
+ reprocess the record will raise an error.
33
+
34
+ == Handle your migrations:
23
35
 
24
36
  rails g dalliance:progress_meter
25
37
 
@@ -11,8 +11,6 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{ Wrapper for an ActiveRecord model with a single ascynhronous method }
12
12
  s.description = %q{ Background processing for ActiveRecord using a 'delayable' worker and a state_machine }
13
13
 
14
- s.rubyforge_project = "dalliance"
15
-
16
14
  s.files = `git ls-files`.split("\n")
17
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -26,6 +24,8 @@ Gem::Specification.new do |s|
26
24
  s.add_development_dependency('delayed_job', '>= 3.0.0')
27
25
  s.add_development_dependency('delayed_job_active_record')
28
26
  s.add_development_dependency('sqlite3')
29
-
30
27
  s.add_development_dependency('resque')
28
+ s.add_development_dependency('bundler-audit')
29
+ s.add_development_dependency('rubocop', '~> 0.78')
30
+ s.add_development_dependency('rspec_junit_formatter')
31
31
  end
@@ -6,7 +6,7 @@ PATH
6
6
  state_machine
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
11
  actionmailer (4.2.9)
12
12
  actionpack (= 4.2.9)
@@ -6,7 +6,7 @@ PATH
6
6
  state_machine
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
11
  actioncable (5.0.0)
12
12
  actionpack (= 5.0.0)
@@ -6,7 +6,7 @@ PATH
6
6
  state_machine
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
11
  actioncable (5.1.7)
12
12
  actionpack (= 5.1.7)
@@ -6,7 +6,7 @@ PATH
6
6
  state_machine
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
11
  actioncable (5.2.3)
12
12
  actionpack (= 5.2.3)
@@ -118,6 +118,10 @@ module Dalliance
118
118
  event :finish_dalliance do
119
119
  transition :processing => :completed
120
120
  end
121
+
122
+ event :reprocess_dalliance do
123
+ transition [:validation_error, :processing_error, :completed] => :pending
124
+ end
121
125
  end
122
126
  #END state_machine(s)
123
127
 
@@ -175,7 +179,9 @@ module Dalliance
175
179
  else
176
180
  self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash.to_yaml )
177
181
  end
182
+ # rubocop:disable Lint/SuppressedException
178
183
  rescue
184
+ # rubocop:enable Lint/SuppressedException
179
185
  end
180
186
  end
181
187
  end
@@ -213,17 +219,40 @@ module Dalliance
213
219
  end
214
220
  end
215
221
 
216
- #Force backgound_processing w/ true
217
- def dalliance_background_process(backgound_processing = nil)
218
- if backgound_processing || (backgound_processing.nil? && self.class.dalliance_options[:background_processing])
219
- self.class.dalliance_options[:worker_class].enqueue(self, processing_queue)
222
+ #Force background_processing w/ true
223
+ def dalliance_background_process(background_processing = nil)
224
+ if background_processing || (background_processing.nil? && self.class.dalliance_options[:background_processing])
225
+ self.class.dalliance_options[:worker_class].enqueue(self, processing_queue, :dalliance_process)
220
226
  else
221
227
  dalliance_process(false)
222
228
  end
223
229
  end
224
230
 
225
- #backgound_processing == false will re-raise any exceptions
226
- def dalliance_process(backgound_processing = false)
231
+ def dalliance_process(background_processing = false)
232
+ do_dalliance_process(
233
+ perform_method: self.class.dalliance_options[:dalliance_method],
234
+ background_processing: background_processing
235
+ )
236
+ end
237
+
238
+ def dalliance_background_reprocess(background_processing = nil)
239
+ if background_processing || (background_processing.nil? && self.class.dalliance_options[:background_processing])
240
+ self.class.dalliance_options[:worker_class].enqueue(self, processing_queue, :dalliance_reprocess)
241
+ else
242
+ dalliance_reprocess(false)
243
+ end
244
+ end
245
+
246
+ def dalliance_reprocess(background_processing = false)
247
+ reprocess_dalliance!
248
+
249
+ do_dalliance_process(
250
+ perform_method: self.class.dalliance_options[:reprocess_method],
251
+ background_processing: background_processing
252
+ )
253
+ end
254
+
255
+ def do_dalliance_process(perform_method:, background_processing: false)
227
256
  start_time = Time.now
228
257
 
229
258
  begin
@@ -233,7 +262,7 @@ module Dalliance
233
262
  build_dalliance_progress_meter(:total_count => calculate_dalliance_progress_meter_total_count).save!
234
263
  end
235
264
 
236
- self.send(self.class.dalliance_options[:dalliance_method])
265
+ self.send(perform_method)
237
266
 
238
267
  finish_dalliance! unless validation_error?
239
268
  rescue StandardError => e
@@ -255,14 +284,16 @@ module Dalliance
255
284
  else
256
285
  self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash.to_yaml )
257
286
  end
287
+ # rubocop:disable Lint/SuppressedException
258
288
  rescue
289
+ # rubocop:enable Lint/SuppressedException
259
290
  end
260
291
  end
261
292
 
262
293
  error_notifier.call(e)
263
294
 
264
- #Don't raise the error if we're backgound_processing...
265
- raise e unless backgound_processing && self.class.dalliance_options[:worker_class].rescue_error?
295
+ # Don't raise the error if we're background processing...
296
+ raise e unless background_processing && self.class.dalliance_options[:worker_class].rescue_error?
266
297
  ensure
267
298
  if self.class.dalliance_options[:dalliance_progress_meter] && dalliance_progress_meter
268
299
  #Works with optimistic locking...
@@ -274,8 +305,11 @@ module Dalliance
274
305
 
275
306
  dalliance_log("[dalliance] #{self.class.name}(#{id}) - #{dalliance_status} #{duration.to_i}")
276
307
 
277
- if self.class.dalliance_options[:duration_column]
278
- self.class.where(id: self.id).update_all(self.class.dalliance_options[:duration_column] => duration.to_i)
308
+ duration_column = self.class.dalliance_options[:duration_column]
309
+ if duration_column.present?
310
+ current_duration = self.send(duration_column) || 0
311
+ self.class.where(id: self.id)
312
+ .update_all(duration_column => current_duration + duration.to_f)
279
313
  end
280
314
  end
281
315
  end
@@ -313,15 +347,28 @@ module Dalliance
313
347
  end
314
348
 
315
349
  module ClassMethods
316
- def dalliance(*args)
317
- options = args.last.is_a?(Hash) ? Dalliance.options.merge(args.pop) : Dalliance.options
318
-
319
- case args.length
320
- when 1
321
- options[:dalliance_method] = args[0]
322
- else
323
- raise ArgumentError, "Incorrect number of Arguements provided"
324
- end
350
+ # Enables dalliance processing for this class.
351
+ #
352
+ # @param [Symbol|String] dalliance_method
353
+ # the name of the method to call when processing the model in dalliance
354
+ # @param [Hash] options
355
+ # an optional hash of options for dalliance processing
356
+ # @option options [Symbol] :reprocess_method
357
+ # the name of the method to use to reprocess the model in dalliance
358
+ # @option options [Boolean] :dalliance_process_meter
359
+ # whether or not to display a progress meter
360
+ # @option options [String] :queue
361
+ # the name of the worker queue to use. Default 'dalliance'
362
+ # @option options [String] :duration_column
363
+ # the name of the table column that stores the dalliance processing time. Default 'dalliance_duration'
364
+ # @option options [Object] :logger
365
+ # the logger object to use. Can be nil
366
+ # @option options [Proc] :error_notifier
367
+ # A proc that accepts an error object. Default is a NOP
368
+ def dalliance(dalliance_method, options = {})
369
+ opts = Dalliance.options.merge(options)
370
+
371
+ opts[:dalliance_method] = dalliance_method
325
372
 
326
373
  if dalliance_options.nil?
327
374
  self.dalliance_options = {}
@@ -329,7 +376,7 @@ module Dalliance
329
376
  self.dalliance_options = self.dalliance_options.dup
330
377
  end
331
378
 
332
- self.dalliance_options.merge!(options)
379
+ self.dalliance_options.merge!(opts)
333
380
 
334
381
  include Dalliance
335
382
  end
@@ -7,7 +7,7 @@ module Dalliance
7
7
  ActiveSupport.on_load :active_record do
8
8
  include Dalliance::Glue
9
9
 
10
- ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Dalliance::Schema)
10
+ ActiveRecord::ConnectionAdapters::TableDefinition.include Dalliance::Schema
11
11
  end
12
12
  end
13
13
  end
@@ -46,20 +46,20 @@ module Dalliance
46
46
  #TODO: This is just a stopgap until I fix increment! to be thread-safe
47
47
  def progress
48
48
  begin
49
- _progress = (current_count.to_f / total_count.to_f * 100).to_i
49
+ current_progress = (current_count.to_f / total_count.to_f * 100).to_i
50
50
 
51
51
  #Handle an incorrect total_count...
52
- _progress = 100 if _progress > 100
52
+ current_progress = 100 if current_progress > 100
53
53
  rescue
54
54
  #what, are you diving by zero?
55
- _progress = 0
55
+ current_progress = 0
56
56
  end
57
57
 
58
- _progress
58
+ current_progress
59
59
  end
60
60
 
61
61
  def increment!
62
62
  Dalliance::ProgressMeter.increment_counter(:current_count, self.id)
63
63
  end
64
64
  end
65
- end
65
+ end
@@ -1,7 +1,7 @@
1
1
  module Dalliance
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 6
4
+ MINOR = 7
5
5
  TINY = 0
6
6
  PRE = nil
7
7
 
@@ -4,12 +4,17 @@ module Dalliance
4
4
  class DelayedJob < ::ActiveJob::Base
5
5
  queue_as :dalliance
6
6
 
7
- def self.enqueue(instance, queue = 'dalliance')
8
- Dalliance::Workers::DelayedJob.set(queue: queue).perform_later(instance.class.name, instance.id)
7
+ def self.enqueue(instance, queue = 'dalliance', perform_method)
8
+ Dalliance::Workers::DelayedJob
9
+ .set(queue: queue)
10
+ .perform_later(instance.class.name, instance.id, perform_method.to_s)
9
11
  end
10
12
 
11
- def perform(instance_klass, instance_id)
12
- instance_klass.constantize.find(instance_id).dalliance_process(true)
13
+ def perform(instance_klass, instance_id, perform_method)
14
+ instance_klass
15
+ .constantize
16
+ .find(instance_id)
17
+ .send(perform_method, true)
13
18
  end
14
19
 
15
20
  #Delayed job automatically retries, so rescue the error
@@ -18,13 +23,19 @@ module Dalliance
18
23
  end
19
24
  end
20
25
  else
21
- class DelayedJob < Struct.new(:instance_klass, :instance_id)
22
- def self.enqueue(instance, queue = 'dalliance')
23
- ::Delayed::Job.enqueue(self.new(instance.class.name, instance.id), :queue => queue)
26
+ class DelayedJob < Struct.new(:instance_klass, :instance_id, :perform_method)
27
+ def self.enqueue(instance, queue = 'dalliance', perform_method)
28
+ ::Delayed::Job.enqueue(
29
+ self.new(instance.class.name, instance.id, perform_method),
30
+ :queue => queue
31
+ )
24
32
  end
25
33
 
26
34
  def perform
27
- instance_klass.constantize.find(instance_id).dalliance_process(true)
35
+ instance_klass
36
+ .constantize
37
+ .find(instance_id)
38
+ .send(perform_method, true)
28
39
  end
29
40
 
30
41
  #Delayed job automatically retries, so rescue the error
@@ -4,12 +4,17 @@ module Dalliance
4
4
  class Resque < ::ActiveJob::Base
5
5
  queue_as :dalliance
6
6
 
7
- def self.enqueue(instance, queue = 'dalliance')
8
- Dalliance::Workers::Resque.set(queue: queue).perform_later(instance.class.name, instance.id)
7
+ def self.enqueue(instance, queue = 'dalliance', perform_method)
8
+ Dalliance::Workers::Resque
9
+ .set(queue: queue)
10
+ .perform_later(instance.class.name, instance.id, perform_method.to_s)
9
11
  end
10
12
 
11
- def perform(instance_klass, instance_id)
12
- instance_klass.constantize.find(instance_id).dalliance_process(true)
13
+ def perform(instance_klass, instance_id, perform_method)
14
+ instance_klass
15
+ .constantize
16
+ .find(instance_id)
17
+ .send(perform_method, true)
13
18
  end
14
19
 
15
20
  #Resque fails, so don't rescue the error
@@ -19,12 +24,15 @@ module Dalliance
19
24
  end
20
25
  else
21
26
  class Resque
22
- def self.enqueue(instance, queue = 'dalliance')
23
- ::Resque.enqueue_to(queue, self, instance.class.name, instance.id)
27
+ def self.enqueue(instance, queue = 'dalliance', perform_method)
28
+ ::Resque.enqueue_to(queue, self, instance.class.name, instance.id, perform_method.to_s)
24
29
  end
25
30
 
26
- def self.perform(instance_klass, instance_id)
27
- instance_klass.constantize.find(instance_id).dalliance_process(true)
31
+ def self.perform(instance_klass, instance_id, perform_method)
32
+ instance_klass
33
+ .constantize
34
+ .find(instance_id)
35
+ .send(perform_method, true)
28
36
  end
29
37
 
30
38
  #Resque fails, so don't rescue the error
@@ -77,6 +77,37 @@ RSpec.describe DallianceModel do
77
77
  expect(subject.dalliance_duration).not_to eq(nil)
78
78
  end
79
79
 
80
+ context 'reprocess' do
81
+ before(:all) do
82
+ DallianceModel.dalliance_options[:worker_class] = Dalliance::Workers::DelayedJob
83
+ DallianceModel.dalliance_options[:queue] = 'dalliance'
84
+ end
85
+
86
+ before do
87
+ subject.dalliance_process
88
+ subject.reload
89
+ end
90
+
91
+ it 'successfully runs the dalliance_reprocess method' do
92
+ subject.dalliance_background_reprocess
93
+ Delayed::Worker.new(:queues => [:dalliance]).work_off
94
+ subject.reload
95
+
96
+ expect(subject).to be_successful
97
+ expect(Delayed::Job.count).to eq(0)
98
+ expect(subject.reprocessed_count).to eq(1)
99
+ end
100
+
101
+ it 'increases the total processing time counter' do
102
+ original_duration = subject.dalliance_duration
103
+ subject.dalliance_background_reprocess
104
+ Delayed::Worker.new(:queues => [:dalliance]).work_off
105
+ subject.reload
106
+
107
+ expect(subject.dalliance_duration).to be_between(original_duration, Float::INFINITY)
108
+ end
109
+ end
110
+
80
111
  context "another_queue" do
81
112
  let(:queue) { 'dalliance_2'}
82
113
 
@@ -114,6 +114,44 @@ RSpec.describe DallianceModel do
114
114
  end
115
115
  end
116
116
 
117
+ context 'reprocess' do
118
+ before :all do
119
+ DallianceModel.dalliance_options[:worker_class] = Dalliance::Workers::Resque
120
+ DallianceModel.dalliance_options[:queue] = 'dalliance'
121
+ end
122
+
123
+ before do
124
+ subject.dalliance_process
125
+ subject.reload
126
+ end
127
+
128
+ it 'successfully runs the dalliance_reprocess method' do
129
+ Resque::Stat.clear(:processed)
130
+ Resque::Stat.clear(:failed)
131
+
132
+ subject.dalliance_background_reprocess
133
+ Resque::Worker.new(:dalliance).process
134
+ subject.reload
135
+
136
+ aggregate_failures do
137
+ expect(subject).to be_successful
138
+ expect(Resque.size(:dalliance)).to eq(0)
139
+ expect(Resque::Stat[:processed]).to eq(1)
140
+ expect(Resque::Stat[:failed]).to eq(0)
141
+ expect(subject.reprocessed_count).to eq(1)
142
+ end
143
+ end
144
+
145
+ it 'increases the total processing time counter' do
146
+ original_duration = subject.dalliance_duration
147
+ subject.dalliance_background_reprocess
148
+ Delayed::Worker.new(:queues => [:dalliance]).work_off
149
+ subject.reload
150
+
151
+ expect(subject.dalliance_duration).to be_between(original_duration, Float::INFINITY)
152
+ end
153
+ end
154
+
117
155
  context "raise error" do
118
156
  before(:all) do
119
157
  DallianceModel.dalliance_options[:dalliance_method] = :dalliance_error_method
@@ -21,7 +21,7 @@ RSpec.describe 'Dalliance' do
21
21
 
22
22
  context "human_attribute_name" do
23
23
  it "should display the correct locale" do
24
- expect(DallianceModel.human_attribute_name(:dalliance_status)).to eq ('Status')
24
+ expect(DallianceModel.human_attribute_name(:dalliance_status)).to eq('Status')
25
25
  end
26
26
  end
27
27
 
@@ -44,7 +44,7 @@ RSpec.describe 'Dalliance' do
44
44
  end
45
45
 
46
46
  context "w/ args" do
47
- let(:queue) { Proc.new{ |a,b,c| 'dalliance_2' } }
47
+ let(:queue) { Proc.new{ |_a,_b,_c| 'dalliance_2' } }
48
48
 
49
49
  specify{ expect(subject.processing_queue).to eq(queue.call) }
50
50
  end
@@ -35,6 +35,60 @@ RSpec.describe DallianceModel do
35
35
  end
36
36
  end
37
37
 
38
+ context 'reprocess' do
39
+ context 'without having already processed' do
40
+ it 'raises an error' do
41
+ expect { subject.dalliance_background_reprocess }
42
+ .to raise_error(
43
+ StateMachine::InvalidTransition,
44
+ /^Cannot transition dalliance_status via :reprocess_dalliance from :pending.*/
45
+ )
46
+ end
47
+ end
48
+
49
+ context 'when the model has already processed' do
50
+ before do
51
+ subject.dalliance_background_process
52
+ subject.reload
53
+ end
54
+
55
+ it 'calls the dalliance_reprocess method' do
56
+ expect { subject.dalliance_background_reprocess }
57
+ .to change(subject, :reprocessed_count)
58
+ .from(0)
59
+ .to(1)
60
+ end
61
+
62
+ it 'can call the dalliance_reprocess method many times in succession' do
63
+ expect { 10.times { subject.dalliance_background_reprocess } }
64
+ .to change(subject, :reprocessed_count)
65
+ .from(0)
66
+ .to(10)
67
+ end
68
+
69
+ it 'sets the dalliance_status to completed' do
70
+ expect { subject.dalliance_background_reprocess }
71
+ .not_to change { subject.reload.dalliance_status }
72
+ .from('completed')
73
+ end
74
+
75
+ it 'sets the dalliance_progress to 100' do
76
+ expect { subject.dalliance_background_reprocess }
77
+ .not_to change { subject.reload.dalliance_progress }
78
+ .from(100)
79
+ end
80
+
81
+ it 'increases the total processing time counter' do
82
+ original_duration = subject.dalliance_duration
83
+ subject.dalliance_background_reprocess
84
+ Delayed::Worker.new(:queues => [:dalliance]).work_off
85
+ subject.reload
86
+
87
+ expect(subject.dalliance_duration).to be_between(original_duration, Float::INFINITY)
88
+ end
89
+ end
90
+ end
91
+
38
92
  context "raise error" do
39
93
  before(:all) do
40
94
  DallianceModel.dalliance_options[:dalliance_method] = :dalliance_error_method
@@ -4,10 +4,12 @@ require 'bundler/setup'
4
4
  #Automatically included in a rails app...
5
5
  require 'active_support'
6
6
 
7
+ # rubocop:disable Lint/SuppressedException
7
8
  begin
8
9
  require 'active_job'
9
10
  rescue LoadError
10
11
  end
12
+ # rubocop:enable Lint/SuppressedException
11
13
 
12
14
  require 'state_machine'
13
15
  require 'byebug'
@@ -35,9 +35,10 @@ ActiveRecord::Schema.define do
35
35
  create_table :dalliance_models, :force => true do |t|
36
36
  t.text :dalliance_error_hash
37
37
  t.string :dalliance_status, :string, :null => false, :default => 'pending'
38
- t.integer :dalliance_duration
38
+ t.decimal :dalliance_duration
39
39
 
40
40
  t.boolean :successful, :default => false
41
+ t.integer :reprocessed_count, default: 0
41
42
  end
42
43
  end
43
44
 
@@ -47,12 +48,17 @@ class DallianceModel < ActiveRecord::Base
47
48
  include Dalliance::Glue
48
49
 
49
50
  dalliance :dalliance_success_method,
51
+ reprocess_method: :dalliance_reprocess_method,
50
52
  :logger => nil
51
53
 
52
54
  def dalliance_success_method
53
55
  update_attribute(:successful, true)
54
56
  end
55
57
 
58
+ def dalliance_reprocess_method
59
+ update_attribute(:reprocessed_count, self.reprocessed_count + 1)
60
+ end
61
+
56
62
  def dalliance_error_method
57
63
  raise RuntimeError
58
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalliance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Sullivan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-21 00:00:00.000000000 Z
11
+ date: 2020-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -114,6 +114,48 @@ dependencies:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: bundler-audit
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.78'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.78'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rspec_junit_formatter
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
117
159
  description: " Background processing for ActiveRecord using a 'delayable' worker and
118
160
  a state_machine "
119
161
  email:
@@ -122,6 +164,7 @@ executables: []
122
164
  extensions: []
123
165
  extra_rdoc_files: []
124
166
  files:
167
+ - ".circleci/config.yml"
125
168
  - ".gitignore"
126
169
  - ".rspec"
127
170
  - Appraisals
@@ -176,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
219
  - !ruby/object:Gem::Version
177
220
  version: '0'
178
221
  requirements: []
179
- rubyforge_project: dalliance
222
+ rubyforge_project:
180
223
  rubygems_version: 2.7.6
181
224
  signing_key:
182
225
  specification_version: 4