background_worker 0.7.0 → 0.9.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/CHANGELOG.md +25 -1
- data/README.md +4 -4
- data/lib/background_worker/base.rb +43 -58
- data/lib/background_worker/config.rb +2 -2
- data/lib/background_worker/logging.rb +16 -0
- data/lib/background_worker/persistent_state.rb +5 -5
- data/lib/background_worker/state.rb +47 -0
- data/lib/background_worker/version.rb +1 -1
- data/lib/background_worker/worker_execution.rb +2 -4
- data/lib/background_worker.rb +3 -3
- data/spec/base_spec.rb +50 -2
- data/spec/support/coverage_loader.rb +1 -1
- metadata +4 -5
- data/lib/background_worker/uid.rb +0 -25
- data/spec/uid_spec.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6354bdc8bc64824ab09d3b2666d1bfcab6c6b02f7b5c5e2cab58902e840eaf7b
|
4
|
+
data.tar.gz: 49f0ffc416005df1da66eb112852dc0eb8246978f3e477fdefdccda9eef3e0f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 306de71726dc7d080ce55e51617e926d84cc99b7abec077381ea820e4e2434c63c023e3ed97ac60f0bd15bf230af9533fb0b411544436e9ac4099bf7e2057d15
|
7
|
+
data.tar.gz: f5d75d708b036479a944632f6c38a8be872125ce6c7b8459b72f3f9266a9a2c2cd027aad93a1d59d8ff82d665dec05ef9101bf61b32cc83ab10bcd70a3e214be
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,25 @@
|
|
1
1
|
# Change Log
|
2
|
+
|
2
3
|
All notable changes to this project will be documented in this file.
|
3
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
|
-
This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
|
5
|
+
This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
|
6
|
+
|
7
|
+
## 0.9.0
|
8
|
+
|
9
|
+
- [PLAT-749] Rename `uid` as `job_id` and make it a base property of job.
|
10
|
+
- [PLAT-759] Add callbacks
|
11
|
+
- [PLAT-761] Extract logging concern
|
12
|
+
- [PLAT-760] Extract status concern
|
13
|
+
- [PLAT-762] Perform now and later will return job object
|
14
|
+
- [PLAT-780] Fix callbacks
|
15
|
+
|
16
|
+
## 0.8.1
|
17
|
+
|
18
|
+
- Fix version
|
19
|
+
|
20
|
+
## 0.8.0
|
21
|
+
|
22
|
+
- [PLAT-747] Remove the ability to pass through `method_name`
|
5
23
|
|
6
24
|
## 0.7.0
|
7
25
|
|
@@ -24,14 +42,20 @@ This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
|
|
24
42
|
- [TT-6292] Support Rails 5.2 built-in redis cache, remove legacy supports
|
25
43
|
|
26
44
|
## 0.2.1
|
45
|
+
|
27
46
|
### Fixed
|
47
|
+
|
28
48
|
- [RU-123] Worker disconnecting within transactions in rails 4+
|
29
49
|
|
30
50
|
## 0.2.0
|
51
|
+
|
31
52
|
### Added
|
53
|
+
|
32
54
|
- [RU-79] Release connections after execution for Rails 4
|
33
55
|
|
34
56
|
## 0.1.0
|
57
|
+
|
35
58
|
### Added
|
59
|
+
|
36
60
|
- [TT-1392] Changelog file
|
37
61
|
- [TT-2141] Only verify connections for Rails 3
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ Start by making a worker class which extends from BackgroundWorker::Base
|
|
10
10
|
|
11
11
|
```ruby
|
12
12
|
class MyWorker < BackgroundWorker::Base
|
13
|
-
def
|
13
|
+
def perform(options={})
|
14
14
|
report_progress('Starting')
|
15
15
|
if options[:message].blank?
|
16
16
|
report_failed("No message provided")
|
@@ -27,7 +27,7 @@ Then, when you want to perform a task in the background, use
|
|
27
27
|
klass#perform_in_background which exists in Base:
|
28
28
|
|
29
29
|
```ruby
|
30
|
-
worker_id = MyWorker.
|
30
|
+
worker_id = MyWorker.perform_later(message: "hello!")
|
31
31
|
```
|
32
32
|
|
33
33
|
# Backgrounded
|
@@ -37,8 +37,8 @@ provide an #enqueue_with configuration like so:
|
|
37
37
|
|
38
38
|
```ruby
|
39
39
|
BackgroundWorker.configure(
|
40
|
-
enqueue_with: -> klass,
|
41
|
-
Resque.enqueue(klass,
|
40
|
+
enqueue_with: -> klass, options {
|
41
|
+
Resque.enqueue(klass, options)
|
42
42
|
}
|
43
43
|
)
|
44
44
|
```
|
@@ -1,88 +1,57 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/callbacks"
|
2
2
|
require 'background_worker/persistent_state'
|
3
3
|
require 'background_worker/worker_execution'
|
4
|
+
require 'background_worker/logging'
|
5
|
+
require 'background_worker/state'
|
4
6
|
|
5
7
|
module BackgroundWorker
|
6
8
|
class Base
|
7
|
-
|
9
|
+
include ActiveSupport::Callbacks
|
10
|
+
include BackgroundWorker::Logging
|
11
|
+
include BackgroundWorker::State
|
12
|
+
attr_accessor :job_id, :options
|
13
|
+
define_callbacks :perform
|
14
|
+
define_callbacks :enqueue
|
8
15
|
|
9
16
|
def initialize(options = {})
|
10
|
-
@
|
17
|
+
@options = options.symbolize_keys
|
18
|
+
@job_id = @options[:job_id] || SecureRandom.uuid
|
11
19
|
|
12
|
-
# Store state persistently, to enable status checkups & progress reporting
|
13
|
-
@state = BackgroundWorker::PersistentState.new(@uid, options.except(:uid))
|
14
20
|
log("Created #{self.class}")
|
15
|
-
log("Options are: #{options.inspect}")
|
21
|
+
log("Options are: #{@options.inspect}")
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
# Report a minor progress -- may get called a lot, so don't save it so often
|
25
|
-
def report_minor_progress(message)
|
26
|
-
state.message = message
|
27
|
-
|
28
|
-
# Only report minor events once per second
|
29
|
-
@last_report ||= Time.now - 2
|
30
|
-
time_elapsed = Time.now - @last_report
|
31
|
-
return unless time_elapsed > 1
|
32
|
-
|
33
|
-
@last_report = Time.now
|
34
|
-
state.save
|
35
|
-
end
|
36
|
-
|
37
|
-
def report_successful(message = 'Finished successfully')
|
38
|
-
state.set_completed(message, :successful)
|
39
|
-
end
|
40
|
-
|
41
|
-
def report_failed(message = 'Failed', detailed_message = nil)
|
42
|
-
state.detailed_message = detailed_message
|
43
|
-
state.set_completed(message, :failed)
|
44
|
-
end
|
45
|
-
|
46
|
-
def logger
|
47
|
-
BackgroundWorker.logger
|
24
|
+
def perform_now(options)
|
25
|
+
run_callbacks :perform do
|
26
|
+
perform(options)
|
27
|
+
end
|
48
28
|
end
|
49
29
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
30
|
+
def enqueue(klass)
|
31
|
+
run_callbacks :enqueue do
|
32
|
+
BackgroundWorker.enqueue(klass, options.merge(job_id: job_id))
|
33
|
+
end
|
53
34
|
end
|
54
35
|
|
55
36
|
class << self
|
56
37
|
attr_reader :queue
|
57
|
-
def get_state_of(worker_id)
|
58
|
-
BackgroundWorker::PersistentState.get_state_of(worker_id)
|
59
|
-
end
|
60
38
|
|
61
39
|
# Public method to do in background...
|
62
|
-
def perform_later(
|
63
|
-
|
64
|
-
|
65
|
-
method_name = method_name.to_sym
|
66
|
-
opts[:uid] ||= BackgroundWorker::Uid.new(to_s, method_name).generate
|
67
|
-
|
68
|
-
# Store into shared-cache before kicking job off
|
69
|
-
BackgroundWorker::PersistentState.new(opts[:uid], opts.except(:uid))
|
70
|
-
|
40
|
+
def perform_later(options = {})
|
41
|
+
worker = new(options)
|
71
42
|
# Enqueue to the background queue
|
72
|
-
|
73
|
-
|
74
|
-
opts[:uid]
|
43
|
+
worker.enqueue(self)
|
44
|
+
worker
|
75
45
|
end
|
76
46
|
|
77
47
|
# This method is called by the job runner
|
78
|
-
|
79
|
-
# It will just call your preferred method in the worker.
|
80
|
-
def perform_now(method_name, options = {})
|
48
|
+
def perform_now(options = {})
|
81
49
|
BackgroundWorker.verify_active_connections! if BackgroundWorker.config.backgrounded
|
82
50
|
|
83
51
|
worker = new(options)
|
84
|
-
execution = WorkerExecution.new(worker,
|
52
|
+
execution = WorkerExecution.new(worker, options)
|
85
53
|
execution.call
|
54
|
+
worker
|
86
55
|
ensure
|
87
56
|
BackgroundWorker.release_connections! if BackgroundWorker.config.backgrounded
|
88
57
|
end
|
@@ -90,6 +59,22 @@ module BackgroundWorker
|
|
90
59
|
def queue_as(queue = nil)
|
91
60
|
@queue = queue&.to_sym || :default
|
92
61
|
end
|
62
|
+
|
63
|
+
def before_perform(*filters, &blk)
|
64
|
+
set_callback(:perform, :before, *filters, &blk)
|
65
|
+
end
|
66
|
+
|
67
|
+
def after_perform(*filters, &blk)
|
68
|
+
set_callback(:perform, :after, *filters, &blk)
|
69
|
+
end
|
70
|
+
|
71
|
+
def before_enqueue(*filters, &blk)
|
72
|
+
set_callback(:enqueue, :before, *filters, &blk)
|
73
|
+
end
|
74
|
+
|
75
|
+
def after_enqueue(*filters, &blk)
|
76
|
+
set_callback(:enqueue, :after, *filters, &blk)
|
77
|
+
end
|
93
78
|
end
|
94
79
|
end
|
95
80
|
end
|
@@ -27,8 +27,8 @@ module BackgroundWorker
|
|
27
27
|
@after_exception.call(e)
|
28
28
|
end
|
29
29
|
|
30
|
-
def foreground_enqueue(klass,
|
31
|
-
klass.perform_now(
|
30
|
+
def foreground_enqueue(klass, opts)
|
31
|
+
klass.perform_now(opts)
|
32
32
|
end
|
33
33
|
|
34
34
|
def default_after_exception(e)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module BackgroundWorker
|
4
|
+
module Logging
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def logger
|
8
|
+
BackgroundWorker.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def log(message, options = {})
|
12
|
+
severity = options.fetch(:severity, :info)
|
13
|
+
logger.send(severity, "job_id=#{job_id} #{message}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -7,12 +7,12 @@ module BackgroundWorker
|
|
7
7
|
class PersistentState
|
8
8
|
attr_accessor :message, :detailed_message, :status, :completed, :data
|
9
9
|
|
10
|
-
def initialize(
|
10
|
+
def initialize(job_id, data)
|
11
11
|
@message = 'Waiting for task to queue...'
|
12
12
|
@status = :processing
|
13
13
|
@completed = false
|
14
14
|
|
15
|
-
@
|
15
|
+
@job_id = job_id
|
16
16
|
@data = data
|
17
17
|
save
|
18
18
|
end
|
@@ -27,13 +27,13 @@ module BackgroundWorker
|
|
27
27
|
|
28
28
|
# Save persistently (well for an hour at least)
|
29
29
|
def save
|
30
|
-
Rails.cache.write(@
|
30
|
+
Rails.cache.write(@job_id, generate_persistent_hash, expires_in: 1.hour)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Get a report out the queue
|
34
34
|
# (was .get_report, then .progress)
|
35
|
-
def self.get_state_of(
|
36
|
-
Rails.cache.read(
|
35
|
+
def self.get_state_of(job_id)
|
36
|
+
Rails.cache.read(job_id)
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module BackgroundWorker
|
4
|
+
module State
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
attr_accessor :state
|
7
|
+
|
8
|
+
# Report progress...
|
9
|
+
def report_progress(message)
|
10
|
+
state.message = message
|
11
|
+
state.save
|
12
|
+
end
|
13
|
+
|
14
|
+
# Report a minor progress -- may get called a lot, so don't save it so often
|
15
|
+
def report_minor_progress(message)
|
16
|
+
state.message = message
|
17
|
+
|
18
|
+
# Only report minor events once per second
|
19
|
+
@last_report ||= Time.now - 2
|
20
|
+
time_elapsed = Time.now - @last_report
|
21
|
+
return unless time_elapsed > 1
|
22
|
+
|
23
|
+
@last_report = Time.now
|
24
|
+
state.save
|
25
|
+
end
|
26
|
+
|
27
|
+
def report_successful(message = 'Finished successfully')
|
28
|
+
state.set_completed(message, :successful)
|
29
|
+
end
|
30
|
+
|
31
|
+
def report_failed(message = 'Failed', detailed_message = nil)
|
32
|
+
state.detailed_message = detailed_message
|
33
|
+
state.set_completed(message, :failed)
|
34
|
+
end
|
35
|
+
|
36
|
+
def state
|
37
|
+
# Store state persistently, to enable status checkups & progress reporting
|
38
|
+
@state ||= BackgroundWorker::PersistentState.new(job_id, @options)
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
def get_state_of(job_id)
|
43
|
+
BackgroundWorker::PersistentState.get_state_of(job_id)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -2,15 +2,13 @@ module BackgroundWorker
|
|
2
2
|
class WorkerExecution
|
3
3
|
attr_reader :worker, :method_name, :options
|
4
4
|
|
5
|
-
def initialize(worker,
|
6
|
-
fail ArgumentError, "'uid' is required to identify worker" unless options[:uid].present?
|
5
|
+
def initialize(worker, options)
|
7
6
|
@worker = worker
|
8
|
-
@method_name = method_name
|
9
7
|
@options = options
|
10
8
|
end
|
11
9
|
|
12
10
|
def call
|
13
|
-
worker.
|
11
|
+
worker.perform_now(options)
|
14
12
|
report_implicitly_successful unless completed?
|
15
13
|
|
16
14
|
rescue StandardError => e
|
data/lib/background_worker.rb
CHANGED
@@ -8,15 +8,15 @@ module BackgroundWorker
|
|
8
8
|
# eg:
|
9
9
|
# BackgroundWorker.configure(
|
10
10
|
# logger: Rails.logger,
|
11
|
-
# enqueue_with: -> klass,
|
11
|
+
# enqueue_with: -> klass, opts { Resque.enqueue(klass, opts) },
|
12
12
|
# after_exception: -> e { Airbrake.notify(e) }
|
13
13
|
# )
|
14
14
|
def self.configure(options)
|
15
15
|
@config = Config.new(options)
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.enqueue(klass,
|
19
|
-
config.enqueue_with.call(klass,
|
18
|
+
def self.enqueue(klass, options)
|
19
|
+
config.enqueue_with.call(klass, options)
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.logger
|
data/spec/base_spec.rb
CHANGED
@@ -18,7 +18,7 @@ describe BackgroundWorker::Base do
|
|
18
18
|
let(:model_class) { Model = Class.new(ActiveRecord::Base) }
|
19
19
|
let(:worker_class) {
|
20
20
|
Class.new(BackgroundWorker::Base) do
|
21
|
-
def
|
21
|
+
def perform(opts)
|
22
22
|
Rails.cache.store(opts[:value])
|
23
23
|
end
|
24
24
|
end
|
@@ -32,7 +32,7 @@ describe BackgroundWorker::Base do
|
|
32
32
|
|
33
33
|
it 'should perform action and handle transactions/connections appropriately' do
|
34
34
|
Model.transaction do
|
35
|
-
worker_class.perform_later(
|
35
|
+
worker_class.perform_later(value: 42)
|
36
36
|
end
|
37
37
|
expect(cache).to have_received(:store).with(42)
|
38
38
|
end
|
@@ -44,3 +44,51 @@ describe BackgroundWorker::Base do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
describe BackgroundWorker::Base do
|
49
|
+
describe 'callbacks' do
|
50
|
+
let(:cache) { double(write: nil, read: nil, reconnect: nil, store: nil) }
|
51
|
+
let(:model_class) { Model = Class.new(ActiveRecord::Base) }
|
52
|
+
|
53
|
+
let(:worker_class) {
|
54
|
+
Class.new(BackgroundWorker::Base) do
|
55
|
+
def perform(opts)
|
56
|
+
Rails.cache.store(opts[:value])
|
57
|
+
end
|
58
|
+
|
59
|
+
before_perform do
|
60
|
+
Rails.cache.store('before_perform_action')
|
61
|
+
end
|
62
|
+
|
63
|
+
after_perform do
|
64
|
+
Rails.cache.store('after_perform_action')
|
65
|
+
end
|
66
|
+
|
67
|
+
before_enqueue do
|
68
|
+
Rails.cache.store('before_enqueue_action')
|
69
|
+
end
|
70
|
+
|
71
|
+
after_enqueue do
|
72
|
+
Rails.cache.store('after_enqueue_action')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
}
|
76
|
+
|
77
|
+
before do
|
78
|
+
stub_const 'Model', model_class
|
79
|
+
stub_const 'Rails', double(cache: cache, env: 'production')
|
80
|
+
BackgroundWorker.configure(backgrounded: false)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should call perform callbacks' do
|
84
|
+
Model.transaction do
|
85
|
+
worker_class.perform_later(value: 42)
|
86
|
+
end
|
87
|
+
expect(cache).to have_received(:store).with('before_enqueue_action')
|
88
|
+
expect(cache).to have_received(:store).with('before_perform_action')
|
89
|
+
expect(cache).to have_received(:store).with(42)
|
90
|
+
expect(cache).to have_received(:store).with('after_perform_action')
|
91
|
+
expect(cache).to have_received(:store).with('after_enqueue_action')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: background_worker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Noack
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-09-
|
13
|
+
date: 2022-09-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -152,15 +152,15 @@ files:
|
|
152
152
|
- lib/background_worker.rb
|
153
153
|
- lib/background_worker/base.rb
|
154
154
|
- lib/background_worker/config.rb
|
155
|
+
- lib/background_worker/logging.rb
|
155
156
|
- lib/background_worker/persistent_state.rb
|
156
|
-
- lib/background_worker/
|
157
|
+
- lib/background_worker/state.rb
|
157
158
|
- lib/background_worker/version.rb
|
158
159
|
- lib/background_worker/worker_execution.rb
|
159
160
|
- spec/base_spec.rb
|
160
161
|
- spec/schema.rb
|
161
162
|
- spec/spec_helper.rb
|
162
163
|
- spec/support/coverage_loader.rb
|
163
|
-
- spec/uid_spec.rb
|
164
164
|
homepage: http://github.com/sealink/background_worker
|
165
165
|
licenses:
|
166
166
|
- MIT
|
@@ -189,4 +189,3 @@ test_files:
|
|
189
189
|
- spec/schema.rb
|
190
190
|
- spec/spec_helper.rb
|
191
191
|
- spec/support/coverage_loader.rb
|
192
|
-
- spec/uid_spec.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# Generates a unique identifier for a particular job identified by class_name/method
|
2
|
-
module BackgroundWorker
|
3
|
-
class Uid
|
4
|
-
attr_reader :class_name, :method
|
5
|
-
|
6
|
-
def initialize(class_name, method)
|
7
|
-
@class_name = class_name
|
8
|
-
@method = method
|
9
|
-
end
|
10
|
-
|
11
|
-
def generate
|
12
|
-
"#{generate_uid_name}:#{generate_uid_hash}"
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def generate_uid_hash
|
18
|
-
::Digest::MD5.hexdigest("#{class_name}:#{method}:#{rand(1 << 64)}:#{Time.now}")
|
19
|
-
end
|
20
|
-
|
21
|
-
def generate_uid_name
|
22
|
-
"#{class_name.underscore}/#{method}".split('/').join(':')
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/uid_spec.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe BackgroundWorker::Uid do
|
4
|
-
let(:class_name) { 'CopyWorker' }
|
5
|
-
let(:method) { 'make_copy' }
|
6
|
-
let(:uid_object) { BackgroundWorker::Uid.new(class_name, method) }
|
7
|
-
|
8
|
-
context '#generate' do
|
9
|
-
subject(:uid) { uid_object.generate }
|
10
|
-
it { is_expected.to match(/copy_worker:make_copy:[0-9a-f]{16}/) }
|
11
|
-
end
|
12
|
-
end
|