sidekiq-activerecord 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -1
- data/.rspec +3 -3
- data/.travis.yml +5 -5
- data/Gemfile +14 -0
- data/README.md +39 -79
- data/lib/sidekiq/active_record/manager_worker.rb +34 -19
- data/lib/sidekiq/active_record/task_worker.rb +119 -71
- data/lib/sidekiq/active_record/version.rb +1 -1
- data/sidekiq-activerecord.gemspec +1 -1
- data/spec/sidekiq/active_record/manager_worker_spec.rb +33 -2
- data/spec/sidekiq/active_record/task_worker_spec.rb +133 -23
- data/spec/spec_helper.rb +4 -0
- metadata +26 -44
- data/Gemfile.lock +0 -71
- data/pkg/sidekiq-activerecord-0.0.1.gem +0 -0
- data/pkg/sidekiq-activerecord-0.0.2.gem +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f4546acc561ce4ce6579666b4b05a66006ec39d9
|
4
|
+
data.tar.gz: 73e5e411912bca36600f5bf091fb010767119f00
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 716f41cd85a9809af9965675eca4220b7d35f5607cb42abfea2fe5c1251fb7d2a8f466219db43bcaefb19e9ab77b604a0926a11482039bb0f89a4333c4fc19af
|
7
|
+
data.tar.gz: b5ec0c789fa00a57ee2464f72a88c40b930dd1683c858d914d8a1330059bf13338abd002d15537ea8419c089e37b76e719495ef34aaa4b1c6490e7b77a8fe018
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
--color
|
2
|
+
--format documentation
|
3
|
+
--require spec_helper
|
data/.travis.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
language: ruby
|
2
|
-
|
3
|
-
|
2
|
+
before_install: gem install bundler
|
3
|
+
script: bundle exec rake
|
4
4
|
rvm:
|
5
5
|
- 1.9.3
|
6
6
|
- jruby-19mode
|
7
|
-
- rbx
|
7
|
+
- rbx-2
|
8
8
|
- 2.0.0
|
9
|
-
- 2.1
|
9
|
+
- 2.1.2
|
10
10
|
matrix:
|
11
11
|
allow_failures:
|
12
|
-
- rvm: rbx
|
12
|
+
- rvm: rbx-2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,116 +1,76 @@
|
|
1
|
-
|
1
|
+
[Sidekiq::Activerecord](https://github.com/sidekiq-orm/sidekiq-activerecord) encapsulates common patterns and various interactions between [Sidekiq](https://github.com/mperham/sidekiq) and [ActiveRecord](http://guides.rubyonrails.org/active_record_basics.html).
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/sidekiq-orm/sidekiq-activerecord.svg?branch=master)](https://travis-ci.org/sidekiq-orm/sidekiq-activerecord)
|
4
4
|
|
5
|
-
|
5
|
+
***
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
gem 'sidekiq-activerecord'
|
10
|
-
|
11
|
-
And then execute:
|
7
|
+
## Common Patterns
|
8
|
+
If you've been using Sidekiq for a while, you've probably noticed a recurring pattern in your workers:
|
12
9
|
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install sidekiq-activerecord
|
18
10
|
|
19
|
-
|
11
|
+
## [Sidekiq::ActiveRecord::TaskWorker](https://github.com/sidekiq-orm/sidekiq-activerecord/wiki/Task-Worker)
|
12
|
+
A very conventional pattern, is to have a worker that gets a model identifier, loads it and runs some custom logic on the model.
|
20
13
|
|
21
|
-
|
14
|
+
[```TaskWorker```]https://github.com/sidekiq-orm/sidekiq-activerecord/wiki/Task-Worker) provides a simple and clean interface, which reduces the boilerplate and exposes only the custom logic.
|
22
15
|
|
23
|
-
|
24
|
-
A parent worker which goes over some model collection and enqueues a child worker for each model in the collection.
|
16
|
+
Here's a simple example:
|
25
17
|
|
26
18
|
```ruby
|
27
|
-
class
|
28
|
-
include Sidekiq::Worker
|
19
|
+
class UserTaskWorker < Sidekiq::ActiveRecord::TaskWorker
|
29
20
|
|
30
|
-
|
31
|
-
User.active.each do |user|
|
32
|
-
ChildWorker.perform_async(user.id)
|
33
|
-
end
|
34
|
-
end
|
21
|
+
sidekiq_task_model :user # or User
|
35
22
|
|
23
|
+
def perform_on_user
|
24
|
+
UserService.run(user)
|
25
|
+
end
|
26
|
+
|
36
27
|
end
|
37
28
|
```
|
29
|
+
For a more see the [TaskWorker documention](https://github.com/sidekiq-orm/sidekiq-activerecord/wiki/Task-Worker).
|
38
30
|
|
39
|
-
## Sidekiq::ManagerWorker - Example
|
40
31
|
|
41
|
-
|
42
|
-
class UserTaskWorker
|
43
|
-
include Sidekiq::TaskWorker
|
44
|
-
end
|
32
|
+
***
|
45
33
|
|
46
|
-
class UserSyncer
|
47
|
-
include Sidekiq::ActiveRecord::ManagerWorker
|
48
34
|
|
35
|
+
## [Sidekiq::ActiveRecord::ManagerWorker](https://github.com/sidekiq-orm/sidekiq-activerecord/wiki/Manager-Worker)
|
36
|
+
Another farily common ```Sidekiq::Worker``` pattern, is a parent worker which goes over a model collection and enqueues a child worker for each model in the collection.
|
37
|
+
|
38
|
+
Here's a simple example:
|
39
|
+
```ruby
|
40
|
+
# Parent Worker
|
41
|
+
class UserSyncer < Sidekiq::ActiveRecord::ManagerWorker
|
49
42
|
sidekiq_delegate_task_to :user_task_worker # or UserTaskWorker
|
50
|
-
sidekiq_manager_options :batch_size => 500,
|
51
|
-
:identifier_key => :user_token,
|
52
|
-
:additional_keys => [:status]
|
53
43
|
end
|
54
|
-
|
55
|
-
UserSyncer.perform_query_async(User.active, :batch_size => 300)
|
56
44
|
```
|
57
|
-
|
58
|
-
## Model Task Workers
|
59
|
-
|
60
|
-
A worker which gets a model.id (like ChildWorker above) loads it, validates it and runs some logic on the model.
|
61
|
-
|
45
|
+
Then, just call the worker with the model collection:
|
62
46
|
```ruby
|
63
|
-
|
64
|
-
include Sidekiq::Worker
|
65
|
-
|
66
|
-
def perform(user_id)
|
67
|
-
user = User.find(user_id)
|
68
|
-
return unless user.present?
|
69
|
-
return unless user.active?
|
70
|
-
|
71
|
-
UserService.run(user)
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
47
|
+
UserSyncer.perform_query_async(User.active)
|
75
48
|
```
|
76
49
|
|
77
|
-
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
class UserMailerTaskWorker
|
81
|
-
include Sidekiq::ActiveRecord::TaskWorker
|
50
|
+
For a more see the [ManagerWorker documention](https://github.com/sidekiq-orm/sidekiq-activerecord/wiki/Manager-Worker).
|
82
51
|
|
83
|
-
|
84
|
-
sidekiq_task_options :identifier_key => :token
|
52
|
+
***
|
85
53
|
|
86
|
-
|
87
|
-
|
88
|
-
end
|
54
|
+
# Documention
|
55
|
+
Checkout the project's [Wiki Page](https://github.com/sidekiq-orm/sidekiq-activerecord/wiki)
|
89
56
|
|
90
|
-
|
91
|
-
def not_found_model(token)
|
92
|
-
Log.error "User not found for token:#{token}"
|
93
|
-
end
|
57
|
+
***
|
94
58
|
|
95
|
-
|
96
|
-
def model_valid?(user)
|
97
|
-
user.active?
|
98
|
-
end
|
59
|
+
# Installation
|
99
60
|
|
100
|
-
|
101
|
-
def invalid_model(user)
|
102
|
-
Log.error "User #{user.token} is invalid"
|
103
|
-
end
|
61
|
+
Add this line to your application's Gemfile:
|
104
62
|
|
105
|
-
|
63
|
+
gem 'sidekiq-activerecord'
|
106
64
|
|
65
|
+
And then execute:
|
107
66
|
|
108
|
-
|
109
|
-
|
67
|
+
$ bundle
|
68
|
+
|
69
|
+
***
|
110
70
|
|
111
71
|
## Contributing
|
112
72
|
|
113
|
-
1. Fork it ( http://github.com/
|
73
|
+
1. Fork it ( http://github.com/sidekiq-orm/sidekiq-activerecord/fork )
|
114
74
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
115
75
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
116
76
|
4. Push to the branch (`git push origin my-new-feature`)
|
@@ -1,17 +1,19 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module ActiveRecord
|
3
|
-
|
4
|
-
|
3
|
+
class ManagerWorker
|
4
|
+
include Sidekiq::Worker
|
5
5
|
|
6
6
|
DEFAULT_IDENTIFIER_KEY = :id
|
7
7
|
DEFAULT_BATCH_SIZE = 1000
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
9
|
+
def perform(options = {})
|
10
|
+
default_query = self.class.get_default_models_query
|
11
|
+
self.class.perform_query_async(default_query, options)
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
15
17
|
# For a given model collection, it delegates each model to a sub-worker (e.g TaskWorker)
|
16
18
|
# Specify the TaskWorker with the `sidekiq_delegate_task_to` method.
|
17
19
|
#
|
@@ -24,7 +26,9 @@ module Sidekiq
|
|
24
26
|
#
|
25
27
|
# @example:
|
26
28
|
# class UserTaskWorker
|
27
|
-
#
|
29
|
+
# def perform(user_id)
|
30
|
+
# # user task logic
|
31
|
+
# end
|
28
32
|
# end
|
29
33
|
#
|
30
34
|
# class UserSyncer
|
@@ -44,7 +48,7 @@ module Sidekiq
|
|
44
48
|
#
|
45
49
|
def perform_query_async(models_query, options = {})
|
46
50
|
set_runtime_options(options)
|
47
|
-
models = models_query
|
51
|
+
models = prepare_models_query(models_query)
|
48
52
|
models.find_in_batches(batch_size: batch_size) do |models_batch|
|
49
53
|
model_attributes = models_batch.map { |model| model_attributes(model) }
|
50
54
|
Sidekiq::Client.push_bulk(class: worker_class, args: model_attributes)
|
@@ -72,10 +76,24 @@ module Sidekiq
|
|
72
76
|
# :additional_keys - additional model keys
|
73
77
|
# :batch_size - Specifies the size of the batch. Default to 1000.
|
74
78
|
def sidekiq_manager_options(opts = {})
|
75
|
-
|
79
|
+
@sidekiq_manager_options_hash = get_sidekiq_manager_options.merge((opts || {}))
|
76
80
|
end
|
77
81
|
|
78
|
-
#
|
82
|
+
# The default of query to run, when the workers runs perform
|
83
|
+
# example
|
84
|
+
# class UserManagerWorker < Sidekiq::ActiveRecord::ManagerWorker
|
85
|
+
# sidekiq_delegate_task_to UserTaskWorker
|
86
|
+
# default_models_query -> { User.active }
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# UserManagerWorker.perform_async(:batch_size => 300)
|
90
|
+
def default_models_query(query)
|
91
|
+
@query = query
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_default_models_query
|
95
|
+
@query.call() if @query.present?
|
96
|
+
end
|
79
97
|
|
80
98
|
def default_worker_manager_options
|
81
99
|
{
|
@@ -93,10 +111,9 @@ module Sidekiq
|
|
93
111
|
additional_attributes.unshift(id_attribute)
|
94
112
|
end
|
95
113
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
attrs
|
114
|
+
def prepare_models_query(models_query)
|
115
|
+
selected_attributes = [models_query.primary_key.to_sym, identifier_key, additional_keys].uniq
|
116
|
+
models_query.select(selected_attributes)
|
100
117
|
end
|
101
118
|
|
102
119
|
def worker_class
|
@@ -104,10 +121,6 @@ module Sidekiq
|
|
104
121
|
manager_options[:worker_class]
|
105
122
|
end
|
106
123
|
|
107
|
-
def default_identifier?
|
108
|
-
identifier_key == DEFAULT_IDENTIFIER_KEY
|
109
|
-
end
|
110
|
-
|
111
124
|
def identifier_key
|
112
125
|
manager_options[:identifier_key]
|
113
126
|
end
|
@@ -125,7 +138,7 @@ module Sidekiq
|
|
125
138
|
end
|
126
139
|
|
127
140
|
def get_sidekiq_manager_options
|
128
|
-
|
141
|
+
@sidekiq_manager_options_hash ||= default_worker_manager_options
|
129
142
|
end
|
130
143
|
|
131
144
|
def runtime_options
|
@@ -135,7 +148,9 @@ module Sidekiq
|
|
135
148
|
def set_runtime_options(options={})
|
136
149
|
@sidekiq_manager_runtime_options = options.delete_if { |_, v| v.to_s.strip == '' }
|
137
150
|
end
|
151
|
+
|
138
152
|
end
|
153
|
+
|
139
154
|
end
|
140
155
|
end
|
141
156
|
end
|
@@ -1,88 +1,86 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module ActiveRecord
|
3
|
-
|
4
|
-
|
3
|
+
class TaskWorker
|
4
|
+
include Sidekiq::Worker
|
5
5
|
|
6
|
-
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
base.class_attribute :sidekiq_task_options_hash
|
9
|
-
end
|
6
|
+
attr_reader :task_model
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
model = fetch_model(identifier)
|
42
|
-
return not_found_model(identifier) unless model.present?
|
43
|
-
|
44
|
-
if model_valid?(model)
|
45
|
-
perform_on_model(model, *args)
|
46
|
-
else
|
47
|
-
invalid_model(model)
|
48
|
-
end
|
49
|
-
end
|
8
|
+
# @example:
|
9
|
+
# class UserMailerTaskWorker < Sidekiq::ActiveRecord::TaskWorker
|
10
|
+
#
|
11
|
+
# sidekiq_task_model :user_model # or UserModel
|
12
|
+
# sidekiq_task_options :identifier_key => :token
|
13
|
+
#
|
14
|
+
# def perform_on_model
|
15
|
+
# UserMailer.deliver_registration_confirmation(user, email_type)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def not_found_model(token)
|
19
|
+
# Log.error "User not found for token:#{token}"
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def should_perform_on_model?
|
23
|
+
# user.active?
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def did_not_perform_on_model
|
27
|
+
# Log.error "User #{user.token} is inactive"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# UserMailerTaskWorker.perform(user.id, :new_email)
|
34
|
+
#
|
35
|
+
def perform(identifier, *args)
|
36
|
+
@task_model = fetch_model(identifier, *args)
|
37
|
+
return not_found_model(identifier, *args) unless @task_model.present?
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
model_klass
|
56
|
-
end
|
57
|
-
get_sidekiq_task_options[:model_class] = model_klass
|
39
|
+
if should_perform_on_model?
|
40
|
+
perform_on_model(*args)
|
41
|
+
else
|
42
|
+
did_not_perform_on_model
|
58
43
|
end
|
44
|
+
end
|
59
45
|
|
60
|
-
|
61
|
-
|
62
|
-
|
46
|
+
def perform_on_model(*args)
|
47
|
+
task_model
|
48
|
+
end
|
63
49
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
50
|
+
# Hook that can block perform_on_model from being triggered,
|
51
|
+
# e.g in cases when the model is no longer valid
|
52
|
+
def should_perform_on_model?
|
53
|
+
true
|
54
|
+
end
|
68
55
|
|
69
|
-
|
70
|
-
|
71
|
-
|
56
|
+
# Hook to handel a model that was not performed
|
57
|
+
def did_not_perform_on_model
|
58
|
+
task_model
|
59
|
+
end
|
72
60
|
|
73
|
-
|
74
|
-
|
75
|
-
|
61
|
+
# Hook to handel not found model
|
62
|
+
def not_found_model(identifier, *args)
|
63
|
+
identifier
|
64
|
+
end
|
76
65
|
|
77
|
-
|
66
|
+
def fetch_model(identifier, *args)
|
67
|
+
self.class.model_class.find_by(self.class.identifier_key => identifier)
|
68
|
+
end
|
78
69
|
|
79
|
-
|
80
|
-
|
70
|
+
|
71
|
+
class << self
|
72
|
+
|
73
|
+
def sidekiq_task_model(model_klass)
|
74
|
+
return if model_klass.blank?
|
75
|
+
|
76
|
+
setup_task_model_alias(model_klass)
|
77
|
+
|
78
|
+
get_sidekiq_task_options[:model_class] = active_record_class(model_klass)
|
81
79
|
end
|
82
80
|
|
83
81
|
def model_class
|
84
82
|
klass = get_sidekiq_task_options[:model_class]
|
85
|
-
fail NotImplementedError.new('`
|
83
|
+
fail NotImplementedError.new('`sidekiq_task_model` was not specified') unless klass.present?
|
86
84
|
klass
|
87
85
|
end
|
88
86
|
|
@@ -96,11 +94,49 @@ module Sidekiq
|
|
96
94
|
#
|
97
95
|
# :identifier_key - the model identifier column. Default 'id'
|
98
96
|
def sidekiq_task_options(opts = {})
|
99
|
-
|
97
|
+
@sidekiq_task_options_hash = get_sidekiq_task_options.merge((opts).symbolize_keys!)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
# aliases task_model with the name of the model
|
104
|
+
#
|
105
|
+
# example:
|
106
|
+
# sidekiq_task_model: AdminUser # or :admin_user
|
107
|
+
#
|
108
|
+
# then the worker will have access to `admin_user`, which is an alias to `task_model`
|
109
|
+
#
|
110
|
+
# def perform_on_admin_user
|
111
|
+
# admin_user == task_model
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# it will add the following method aliases to the hooks:
|
115
|
+
#
|
116
|
+
# def not_found_admin_user; end
|
117
|
+
# def should_perform_on_admin_user?; end
|
118
|
+
# def did_not_perform_on_admin_user; end
|
119
|
+
#
|
120
|
+
def setup_task_model_alias(model_klass_name)
|
121
|
+
if model_klass_name.is_a?(Class)
|
122
|
+
model_klass_name = model_klass_name.name.underscore
|
123
|
+
end
|
124
|
+
{
|
125
|
+
:task_model => model_klass_name,
|
126
|
+
:fetch_model => "fetch_#{model_klass_name}",
|
127
|
+
:not_found_model => "not_found_#{model_klass_name}",
|
128
|
+
:should_perform_on_model? => "should_perform_on_#{model_klass_name}?",
|
129
|
+
:did_not_perform_on_model => "did_not_perform_on_#{model_klass_name}",
|
130
|
+
:perform_on_model => "perform_on_#{model_klass_name}"
|
131
|
+
}.each do |old_name, new_name|
|
132
|
+
self.class_exec do
|
133
|
+
alias_method new_name.to_sym, old_name
|
134
|
+
end
|
135
|
+
end
|
100
136
|
end
|
101
137
|
|
102
138
|
def get_sidekiq_task_options
|
103
|
-
|
139
|
+
@sidekiq_task_options_hash ||= default_worker_task_options
|
104
140
|
end
|
105
141
|
|
106
142
|
def default_worker_task_options
|
@@ -108,7 +144,19 @@ module Sidekiq
|
|
108
144
|
identifier_key: :id
|
109
145
|
}
|
110
146
|
end
|
147
|
+
|
148
|
+
def active_record_class(model_klass)
|
149
|
+
begin
|
150
|
+
model_klass = model_klass.to_s.classify.constantize
|
151
|
+
raise unless model_klass <= ::ActiveRecord::Base
|
152
|
+
rescue
|
153
|
+
fail ArgumentError.new '`sidekiq_task_model` must be an ActiveRecord model'
|
154
|
+
end
|
155
|
+
model_klass
|
156
|
+
end
|
157
|
+
|
111
158
|
end
|
159
|
+
|
112
160
|
end
|
113
161
|
end
|
114
162
|
end
|
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency 'sidekiq', '>= 2.16'
|
22
22
|
spec.add_dependency 'activerecord', '>= 4.0'
|
23
23
|
|
24
|
+
spec.add_development_dependency 'rake'
|
24
25
|
spec.add_development_dependency 'rspec', '3.0.0.rc1'
|
25
26
|
spec.add_development_dependency 'database_cleaner', '>= 1.2.0'
|
26
|
-
spec.add_development_dependency 'sqlite3', '>= 1.3.9'
|
27
27
|
spec.add_development_dependency 'factory_girl', '~> 4.0'
|
28
28
|
end
|
@@ -9,8 +9,7 @@ describe Sidekiq::ActiveRecord::ManagerWorker do
|
|
9
9
|
let(:worker_class) { MockUserWorker }
|
10
10
|
let(:sidekiq_client) { Sidekiq::Client }
|
11
11
|
|
12
|
-
class UserManagerWorker
|
13
|
-
include Sidekiq::ActiveRecord::ManagerWorker
|
12
|
+
class UserManagerWorker < Sidekiq::ActiveRecord::ManagerWorker
|
14
13
|
sidekiq_delegate_task_to MockUserWorker
|
15
14
|
end
|
16
15
|
|
@@ -21,6 +20,24 @@ describe Sidekiq::ActiveRecord::ManagerWorker do
|
|
21
20
|
|
22
21
|
let(:models_query) { User.active }
|
23
22
|
|
23
|
+
describe 'perform with default models query' do
|
24
|
+
|
25
|
+
before do
|
26
|
+
class UserManagerWorker < Sidekiq::ActiveRecord::ManagerWorker
|
27
|
+
sidekiq_delegate_task_to MockUserWorker
|
28
|
+
default_models_query -> { User.active }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:default_models_query) { User.active }
|
33
|
+
let(:worker_options) { {:batch_size => 300} }
|
34
|
+
|
35
|
+
it 'runs `perform_query_async` with the default models query and the specified options' do
|
36
|
+
expect(UserManagerWorker).to receive(:perform_query_async).with(default_models_query, worker_options)
|
37
|
+
UserManagerWorker.new.perform(worker_options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
24
41
|
describe 'perform_query_async' do
|
25
42
|
|
26
43
|
def run_worker(options = {})
|
@@ -37,6 +54,20 @@ describe Sidekiq::ActiveRecord::ManagerWorker do
|
|
37
54
|
|
38
55
|
let(:model_ids) { [[user_1.id], [user_2.id], [user_3.id]] }
|
39
56
|
|
57
|
+
context 'when a sidekiq_options is specified' do
|
58
|
+
|
59
|
+
before do
|
60
|
+
class UserManagerWorker
|
61
|
+
sidekiq_options :queue => :user_manager_queue
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'sets the queue' do
|
66
|
+
sidekiq_options = UserManagerWorker.send(:get_sidekiq_options)
|
67
|
+
expect(sidekiq_options['queue']).to eq :user_manager_queue
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
40
71
|
context 'when the worker_class is specified' do
|
41
72
|
|
42
73
|
class MockCustomWorker; end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
describe Sidekiq::ActiveRecord::TaskWorker do
|
2
2
|
|
3
|
-
class UserTaskWorker
|
4
|
-
include Sidekiq::ActiveRecord::TaskWorker
|
3
|
+
class UserTaskWorker < Sidekiq::ActiveRecord::TaskWorker
|
5
4
|
end
|
6
5
|
|
7
6
|
let!(:user) { create(:user, :active) }
|
8
7
|
|
9
|
-
subject(:
|
8
|
+
subject(:task_worker_class) { UserTaskWorker }
|
9
|
+
subject(:task_worker) { UserTaskWorker.new }
|
10
10
|
|
11
11
|
def run_worker
|
12
12
|
task_worker.perform(user.id)
|
@@ -30,17 +30,51 @@ describe Sidekiq::ActiveRecord::TaskWorker do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'sets the identifier_key' do
|
33
|
-
identifier =
|
33
|
+
identifier = task_worker_class.send(:identifier_key)
|
34
34
|
expect(identifier).to eq :email
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'calls the perform_on_model with the model' do
|
38
|
-
expect(task_worker).to receive(:perform_on_model)
|
38
|
+
expect(task_worker).to receive(:perform_on_model)
|
39
39
|
task_worker.perform(user.email)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
context 'when a
|
43
|
+
context 'when a sidekiq_options is specified' do
|
44
|
+
|
45
|
+
before do
|
46
|
+
class UserTaskWorker
|
47
|
+
sidekiq_options :queue => :user_queue
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets the queue' do
|
52
|
+
sidekiq_options = task_worker_class.send(:get_sidekiq_options)
|
53
|
+
expect(sidekiq_options['queue']).to eq :user_queue
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the specified task model is not a class' do
|
58
|
+
|
59
|
+
it 'raises an ArgumentError' do
|
60
|
+
expect {
|
61
|
+
task_worker_class.send(:sidekiq_task_model, :something_unrelated)
|
62
|
+
}.to raise_error ArgumentError
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when the specified task model is not an ActiveRecord class' do
|
67
|
+
|
68
|
+
class NotActiveRecord; end
|
69
|
+
|
70
|
+
it 'raises an ArgumentError' do
|
71
|
+
expect {
|
72
|
+
task_worker_class.send(:sidekiq_task_model, NotActiveRecord)
|
73
|
+
}.to raise_error ArgumentError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when a ActiveRecord class is specified' do
|
44
78
|
|
45
79
|
before do
|
46
80
|
class UserTaskWorker
|
@@ -49,13 +83,25 @@ describe Sidekiq::ActiveRecord::TaskWorker do
|
|
49
83
|
end
|
50
84
|
|
51
85
|
it 'sets the model' do
|
52
|
-
klass =
|
86
|
+
klass = task_worker_class.send(:model_class)
|
53
87
|
expect(klass).to eq User
|
54
88
|
end
|
55
89
|
|
90
|
+
describe 'task_model' do
|
91
|
+
it 'sets the model' do
|
92
|
+
run_worker
|
93
|
+
expect(task_worker.task_model).to eq user
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'has an alias of `task_model` withe for the specified model name' do
|
97
|
+
run_worker
|
98
|
+
expect(task_worker.user).to eq user
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
56
102
|
end
|
57
103
|
|
58
|
-
context 'when
|
104
|
+
context 'when an ActiveRecord class name is specified' do
|
59
105
|
before do
|
60
106
|
class UserTaskWorker
|
61
107
|
sidekiq_task_model :user
|
@@ -63,20 +109,45 @@ describe Sidekiq::ActiveRecord::TaskWorker do
|
|
63
109
|
end
|
64
110
|
|
65
111
|
it 'sets the model' do
|
66
|
-
klass =
|
112
|
+
klass = task_worker_class.send(:model_class)
|
67
113
|
expect(klass).to eq User
|
68
114
|
end
|
69
115
|
|
116
|
+
describe 'task_model' do
|
117
|
+
it 'sets the model' do
|
118
|
+
run_worker
|
119
|
+
expect(task_worker.task_model).to eq user
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'has an alias of `task_model` withe for the specified model name' do
|
123
|
+
run_worker
|
124
|
+
expect(task_worker.user).to eq user
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'when fetching the model' do
|
129
|
+
|
130
|
+
def run_worker
|
131
|
+
task_worker.perform(user.id, user.email)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'calls the fetch_model hook' do
|
135
|
+
expect(task_worker).to receive(:fetch_model).with(user.id, user.email)
|
136
|
+
run_worker
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
70
141
|
context 'when the model is not found' do
|
71
142
|
|
72
143
|
let(:trash_id) { user.id + 10 }
|
73
144
|
|
74
145
|
def run_worker
|
75
|
-
task_worker.perform(trash_id)
|
146
|
+
task_worker.perform(trash_id, user.email)
|
76
147
|
end
|
77
148
|
|
78
149
|
it 'calls the not_found_model hook' do
|
79
|
-
expect(task_worker).to receive(:not_found_model).with(trash_id)
|
150
|
+
expect(task_worker).to receive(:not_found_model).with(trash_id, user.email)
|
80
151
|
run_worker
|
81
152
|
end
|
82
153
|
|
@@ -84,54 +155,86 @@ describe Sidekiq::ActiveRecord::TaskWorker do
|
|
84
155
|
expect(task_worker).to_not receive(:perform_on_model)
|
85
156
|
run_worker
|
86
157
|
end
|
158
|
+
|
159
|
+
describe 'method alias' do
|
160
|
+
it 'has an alias of not_found_model hook with for the specified task model name' do
|
161
|
+
expect(task_worker.not_found_user(trash_id)).to eq trash_id
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
87
165
|
end
|
88
166
|
|
89
167
|
context 'when the mode is found' do
|
90
168
|
|
91
|
-
context 'when the
|
92
|
-
it 'calls the
|
93
|
-
expect(task_worker).to receive(:
|
169
|
+
context 'when the should_perform_on_model? hook is specified' do
|
170
|
+
it 'calls the should_perform_on_model? hook' do
|
171
|
+
expect(task_worker).to receive(:should_perform_on_model?)
|
94
172
|
run_worker
|
95
173
|
end
|
174
|
+
|
175
|
+
describe 'method alias' do
|
176
|
+
|
177
|
+
let(:mock_result) { 1234 }
|
178
|
+
|
179
|
+
before do
|
180
|
+
class UserTaskWorker
|
181
|
+
def should_perform_on_user?
|
182
|
+
1234
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'has an alias of should_perform_on_model? hook with for the specified task model name' do
|
188
|
+
run_worker
|
189
|
+
expect(task_worker.should_perform_on_user?).to eq mock_result
|
190
|
+
end
|
191
|
+
end
|
96
192
|
end
|
97
193
|
|
98
|
-
context 'when the model
|
194
|
+
context 'when the model should be performed' do
|
99
195
|
|
100
196
|
before do
|
101
|
-
allow(task_worker).to receive(:
|
197
|
+
allow(task_worker).to receive(:should_perform_on_model?).and_return(true)
|
102
198
|
end
|
103
199
|
|
104
200
|
it 'calls the perform_on_model with the model' do
|
105
|
-
expect(task_worker).to receive(:perform_on_model)
|
201
|
+
expect(task_worker).to receive(:perform_on_model)
|
106
202
|
run_worker
|
107
203
|
end
|
108
204
|
|
109
205
|
describe 'perform_on_model' do
|
110
206
|
context 'when passing only the model identifier' do
|
111
207
|
it 'calls the perform_on_model with the model' do
|
112
|
-
expect(task_worker).to receive(:perform_on_model)
|
208
|
+
expect(task_worker).to receive(:perform_on_model)
|
113
209
|
run_worker
|
114
210
|
end
|
115
211
|
end
|
116
212
|
|
117
213
|
context 'when passing additional arguments' do
|
118
214
|
it 'calls the perform_on_model with the model' do
|
119
|
-
expect(task_worker).to receive(:perform_on_model).with(user
|
215
|
+
expect(task_worker).to receive(:perform_on_model).with(user.email)
|
120
216
|
task_worker.perform(user.id, user.email)
|
121
217
|
end
|
122
218
|
end
|
123
219
|
|
220
|
+
describe 'method alias' do
|
221
|
+
it 'has an alias of perform_on_model hook with for the specified task model name' do
|
222
|
+
task_worker.perform(user.id)
|
223
|
+
expect(task_worker.perform_on_user).to eq user
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
124
227
|
end
|
125
228
|
end
|
126
229
|
|
127
|
-
context 'when the model
|
230
|
+
context 'when the model should not be performed' do
|
128
231
|
|
129
232
|
before do
|
130
|
-
allow(task_worker).to receive(:
|
233
|
+
allow(task_worker).to receive(:should_perform_on_model?).and_return(false)
|
131
234
|
end
|
132
235
|
|
133
|
-
it 'calls the
|
134
|
-
expect(task_worker).to receive(:
|
236
|
+
it 'calls the did_not_perform_on_model hook' do
|
237
|
+
expect(task_worker).to receive(:did_not_perform_on_model)
|
135
238
|
run_worker
|
136
239
|
end
|
137
240
|
|
@@ -140,6 +243,13 @@ describe Sidekiq::ActiveRecord::TaskWorker do
|
|
140
243
|
run_worker
|
141
244
|
end
|
142
245
|
|
246
|
+
describe 'method alias' do
|
247
|
+
it 'has an alias of did_not_perform_on_model hook with for the specified task model name' do
|
248
|
+
run_worker
|
249
|
+
expect(task_worker.did_not_perform_on_user).to eq user
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
143
253
|
end
|
144
254
|
|
145
255
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,100 +1,88 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Adam Farhi
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-05
|
11
|
+
date: 2014-06-05 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: sidekiq
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '2.16'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '2.16'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: activerecord
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '4.0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '4.0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
42
|
+
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- - '
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
47
|
+
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- - '
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
54
|
+
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
56
|
+
name: rspec
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '='
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
61
|
+
version: 3.0.0.rc1
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '='
|
76
67
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
68
|
+
version: 3.0.0.rc1
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
70
|
+
name: database_cleaner
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
|
-
version: 1.
|
75
|
+
version: 1.2.0
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
|
-
version: 1.
|
82
|
+
version: 1.2.0
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: factory_girl
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
87
|
- - ~>
|
100
88
|
- !ruby/object:Gem::Version
|
@@ -102,7 +90,6 @@ dependencies:
|
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
94
|
- - ~>
|
108
95
|
- !ruby/object:Gem::Version
|
@@ -118,7 +105,6 @@ files:
|
|
118
105
|
- .rspec
|
119
106
|
- .travis.yml
|
120
107
|
- Gemfile
|
121
|
-
- Gemfile.lock
|
122
108
|
- LICENSE.txt
|
123
109
|
- README.md
|
124
110
|
- Rakefile
|
@@ -126,8 +112,6 @@ files:
|
|
126
112
|
- lib/sidekiq/active_record/task_worker.rb
|
127
113
|
- lib/sidekiq/active_record/version.rb
|
128
114
|
- lib/sidekiq/activerecord.rb
|
129
|
-
- pkg/sidekiq-activerecord-0.0.1.gem
|
130
|
-
- pkg/sidekiq-activerecord-0.0.2.gem
|
131
115
|
- sidekiq-activerecord.gemspec
|
132
116
|
- spec/sidekiq/active_record/manager_worker_spec.rb
|
133
117
|
- spec/sidekiq/active_record/task_worker_spec.rb
|
@@ -139,27 +123,26 @@ files:
|
|
139
123
|
homepage: https://github.com/yelled3/sidekiq-activerecord
|
140
124
|
licenses:
|
141
125
|
- MIT
|
126
|
+
metadata: {}
|
142
127
|
post_install_message:
|
143
128
|
rdoc_options: []
|
144
129
|
require_paths:
|
145
130
|
- lib
|
146
131
|
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
132
|
requirements:
|
149
|
-
- -
|
133
|
+
- - '>='
|
150
134
|
- !ruby/object:Gem::Version
|
151
135
|
version: '0'
|
152
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
137
|
requirements:
|
155
|
-
- -
|
138
|
+
- - '>='
|
156
139
|
- !ruby/object:Gem::Version
|
157
140
|
version: '0'
|
158
141
|
requirements: []
|
159
142
|
rubyforge_project:
|
160
|
-
rubygems_version:
|
143
|
+
rubygems_version: 2.0.6
|
161
144
|
signing_key:
|
162
|
-
specification_version:
|
145
|
+
specification_version: 4
|
163
146
|
summary: Encapsulates various interactions between Sidekiq and ActiveRecord
|
164
147
|
test_files:
|
165
148
|
- spec/sidekiq/active_record/manager_worker_spec.rb
|
@@ -169,4 +152,3 @@ test_files:
|
|
169
152
|
- spec/support/database_cleaner.rb
|
170
153
|
- spec/support/factory_girl.rb
|
171
154
|
- spec/support/models.rb
|
172
|
-
has_rdoc:
|
data/Gemfile.lock
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
sidekiq-activerecord (0.0.2)
|
5
|
-
activerecord (>= 4.0)
|
6
|
-
sidekiq (>= 2.16)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
activemodel (4.1.1)
|
12
|
-
activesupport (= 4.1.1)
|
13
|
-
builder (~> 3.1)
|
14
|
-
activerecord (4.1.1)
|
15
|
-
activemodel (= 4.1.1)
|
16
|
-
activesupport (= 4.1.1)
|
17
|
-
arel (~> 5.0.0)
|
18
|
-
activesupport (4.1.1)
|
19
|
-
i18n (~> 0.6, >= 0.6.9)
|
20
|
-
json (~> 1.7, >= 1.7.7)
|
21
|
-
minitest (~> 5.1)
|
22
|
-
thread_safe (~> 0.1)
|
23
|
-
tzinfo (~> 1.1)
|
24
|
-
arel (5.0.1.20140414130214)
|
25
|
-
builder (3.2.2)
|
26
|
-
celluloid (0.15.2)
|
27
|
-
timers (~> 1.1.0)
|
28
|
-
connection_pool (2.0.0)
|
29
|
-
database_cleaner (1.2.0)
|
30
|
-
diff-lcs (1.2.5)
|
31
|
-
factory_girl (4.4.0)
|
32
|
-
activesupport (>= 3.0.0)
|
33
|
-
i18n (0.6.9)
|
34
|
-
json (1.8.1)
|
35
|
-
minitest (5.3.4)
|
36
|
-
redis (3.0.7)
|
37
|
-
redis-namespace (1.4.1)
|
38
|
-
redis (~> 3.0.4)
|
39
|
-
rspec (3.0.0.rc1)
|
40
|
-
rspec-core (= 3.0.0.rc1)
|
41
|
-
rspec-expectations (= 3.0.0.rc1)
|
42
|
-
rspec-mocks (= 3.0.0.rc1)
|
43
|
-
rspec-core (3.0.0.rc1)
|
44
|
-
rspec-support (= 3.0.0.rc1)
|
45
|
-
rspec-expectations (3.0.0.rc1)
|
46
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
47
|
-
rspec-support (= 3.0.0.rc1)
|
48
|
-
rspec-mocks (3.0.0.rc1)
|
49
|
-
rspec-support (= 3.0.0.rc1)
|
50
|
-
rspec-support (3.0.0.rc1)
|
51
|
-
sidekiq (3.1.0)
|
52
|
-
celluloid (>= 0.15.2)
|
53
|
-
connection_pool (>= 2.0.0)
|
54
|
-
json
|
55
|
-
redis (>= 3.0.6)
|
56
|
-
redis-namespace (>= 1.3.1)
|
57
|
-
sqlite3 (1.3.9)
|
58
|
-
thread_safe (0.3.3)
|
59
|
-
timers (1.1.0)
|
60
|
-
tzinfo (1.1.0)
|
61
|
-
thread_safe (~> 0.1)
|
62
|
-
|
63
|
-
PLATFORMS
|
64
|
-
ruby
|
65
|
-
|
66
|
-
DEPENDENCIES
|
67
|
-
database_cleaner (>= 1.2.0)
|
68
|
-
factory_girl (~> 4.0)
|
69
|
-
rspec (= 3.0.0.rc1)
|
70
|
-
sidekiq-activerecord!
|
71
|
-
sqlite3 (>= 1.3.9)
|
Binary file
|
Binary file
|