background_worker 0.7.0 → 0.9.0

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: 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