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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37f371795b57bf7461a9f02c9f74195daf9d3cb61328fd0eca5f69a2c61447b6
4
- data.tar.gz: 393896f93efac8a56c0806a8664ea381fff12ff31a2e0e31c210d6a3480694b8
3
+ metadata.gz: 6354bdc8bc64824ab09d3b2666d1bfcab6c6b02f7b5c5e2cab58902e840eaf7b
4
+ data.tar.gz: 49f0ffc416005df1da66eb112852dc0eb8246978f3e477fdefdccda9eef3e0f5
5
5
  SHA512:
6
- metadata.gz: dae022eecbd54ce73185739df605b3fa5ffd1efc12e411d86bd76f6bfac03f4e20616ac20ffdda04d7c3ef3c3d3d403dac69754a45b5ca9d6fb57daab2444acc
7
- data.tar.gz: 0f9f04c606150a637744facdc4c9d9bb02ff1918d52b24fd92f5ebb47ec3606aab2e59567355422b485924352cc471f29e18d4be6438378e3ead11e0aeff3c96
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 my_task(options={})
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.perform_in_background(:my_task, message: "hello!")
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, method_name, options {
41
- Resque.enqueue(klass, method_name, options)
40
+ enqueue_with: -> klass, options {
41
+ Resque.enqueue(klass, options)
42
42
  }
43
43
  )
44
44
  ```
@@ -1,88 +1,57 @@
1
- require 'background_worker/uid'
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
- attr_accessor :uid, :state
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
- @uid = options[:uid]
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
- # Report progress...
19
- def report_progress(message)
20
- state.message = message
21
- state.save
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 log(message, options = {})
51
- severity = options.fetch(:severity, :info)
52
- logger.send(severity, "uid=#{uid} #{message}")
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(method_name, options = {})
63
- opts = options.symbolize_keys
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
- BackgroundWorker.enqueue(self, method_name, opts)
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, method_name, options)
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, method_name, opts)
31
- klass.perform_now(method_name, opts)
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(worker_uid, data)
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
- @worker_uid = worker_uid
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(@worker_uid, generate_persistent_hash, expires_in: 1.hour)
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(worker_uid)
36
- Rails.cache.read(worker_uid)
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
@@ -1,3 +1,3 @@
1
1
  module BackgroundWorker
2
- VERSION = '0.7.0'
2
+ VERSION = '0.9.0'
3
3
  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, method_name, options)
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.send(method_name, options)
11
+ worker.perform_now(options)
14
12
  report_implicitly_successful unless completed?
15
13
 
16
14
  rescue StandardError => e
@@ -8,15 +8,15 @@ module BackgroundWorker
8
8
  # eg:
9
9
  # BackgroundWorker.configure(
10
10
  # logger: Rails.logger,
11
- # enqueue_with: -> klass, method_name, opts { Resque.enqueue(klass, method_name, opts) },
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, method_name, options)
19
- config.enqueue_with.call(klass, method_name, options)
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 store_in_cache(opts)
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(:store_in_cache, value: 42)
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
@@ -1,3 +1,3 @@
1
1
  require 'coverage/kit'
2
2
 
3
- Coverage::Kit.setup(minimum_coverage: 82.75)
3
+ Coverage::Kit.setup(minimum_coverage: 84.60)
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.7.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-07 00:00:00.000000000 Z
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/uid.rb
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