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 +4 -4
- data/.circleci/config.yml +107 -0
- data/Gemfile +1 -1
- data/README.rdoc +13 -1
- data/dalliance.gemspec +3 -3
- data/gemfiles/rails_4.2.gemfile.lock +1 -1
- data/gemfiles/rails_5.0.gemfile.lock +1 -1
- data/gemfiles/rails_5.1.gemfile.lock +1 -1
- data/gemfiles/rails_5.2.gemfile.lock +1 -1
- data/lib/dalliance.rb +68 -21
- data/lib/dalliance/engine.rb +1 -1
- data/lib/dalliance/progress_meter.rb +5 -5
- data/lib/dalliance/version.rb +1 -1
- data/lib/dalliance/workers/delayed_job.rb +19 -8
- data/lib/dalliance/workers/resque.rb +16 -8
- data/spec/dalliance/asynchronous_delayed_job_spec.rb +31 -0
- data/spec/dalliance/asynchronous_resque_spec.rb +38 -0
- data/spec/dalliance/dalliance_spec.rb +2 -2
- data/spec/dalliance/synchronous_spec.rb +54 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/active_record.rb +7 -1
- metadata +46 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfda33ea2cc9d97c6896fbab7cfb6d3c644ce56c64f22632c5e744544770a853
|
4
|
+
data.tar.gz: cdd5a93b644a426edc9a4007ef65c373aebe6fe9aac7b30f3096a47fdfaa11e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/README.rdoc
CHANGED
@@ -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
|
-
|
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
|
|
data/dalliance.gemspec
CHANGED
@@ -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
|
data/lib/dalliance.rb
CHANGED
@@ -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
|
217
|
-
def dalliance_background_process(
|
218
|
-
if
|
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
|
-
|
226
|
-
|
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(
|
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
|
265
|
-
raise e unless
|
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
|
-
|
278
|
-
|
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
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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!(
|
379
|
+
self.dalliance_options.merge!(opts)
|
333
380
|
|
334
381
|
include Dalliance
|
335
382
|
end
|
data/lib/dalliance/engine.rb
CHANGED
@@ -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.
|
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
|
-
|
49
|
+
current_progress = (current_count.to_f / total_count.to_f * 100).to_i
|
50
50
|
|
51
51
|
#Handle an incorrect total_count...
|
52
|
-
|
52
|
+
current_progress = 100 if current_progress > 100
|
53
53
|
rescue
|
54
54
|
#what, are you diving by zero?
|
55
|
-
|
55
|
+
current_progress = 0
|
56
56
|
end
|
57
57
|
|
58
|
-
|
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
|
data/lib/dalliance/version.rb
CHANGED
@@ -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
|
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
|
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(
|
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
|
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
|
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
|
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
|
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
|
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{ |
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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.
|
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.
|
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:
|
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:
|
222
|
+
rubyforge_project:
|
180
223
|
rubygems_version: 2.7.6
|
181
224
|
signing_key:
|
182
225
|
specification_version: 4
|