sidekiq_simple_delay 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +55 -2
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +47 -1
- data/README.md +55 -1
- data/lib/sidekiq_simple_delay.rb +72 -2
- data/lib/sidekiq_simple_delay/delay_methods.rb +92 -3
- data/lib/sidekiq_simple_delay/delay_worker.rb +1 -2
- data/lib/sidekiq_simple_delay/delayed_mailer.rb +37 -0
- data/lib/sidekiq_simple_delay/extensions/action_mailer.rb +21 -0
- data/lib/sidekiq_simple_delay/extensions/active_record.rb +27 -0
- data/lib/sidekiq_simple_delay/utils.rb +22 -0
- data/lib/sidekiq_simple_delay/version.rb +1 -1
- data/run_specs +8 -2
- data/sidekiq_simple_delay.gemspec +2 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec1fe6b079ffe00f678759842aabf1c0b541e963559ef96ffebd2a2ed320c8f1
|
4
|
+
data.tar.gz: a1539286fa1b0a82e25596d9a69741c601f5392c2a3372e811486f5adcd3af45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dd22a43966e73eb3adfdc5b9d3cd91158fa705f587368603a4edae954aedf713d619d32a03f1102002ae1f593eca25fba178d3984a0208e49b6973a7636ebc3
|
7
|
+
data.tar.gz: 024d186c564d19b6298bedddc0e5b0c2dd73ec7925c9c02a2fe04d706785354fab9162153284c8b14670329827ccf637a743d33b50b4fc375d1d009db9204a53
|
data/.circleci/config.yml
CHANGED
@@ -26,7 +26,7 @@ spec_shared: &spec_shared
|
|
26
26
|
--format RspecJunitFormatter \
|
27
27
|
--out /tmp/test-results/rspec-basic.xml \
|
28
28
|
--format progress \
|
29
|
-
spec --tag ~
|
29
|
+
spec --tag ~run_tag
|
30
30
|
|
31
31
|
- run:
|
32
32
|
name: Run enable_delay specs
|
@@ -35,7 +35,60 @@ spec_shared: &spec_shared
|
|
35
35
|
--format RspecJunitFormatter \
|
36
36
|
--out /tmp/test-results/rspec-basic.xml \
|
37
37
|
--format progress \
|
38
|
-
spec --tag enable_delay
|
38
|
+
spec --tag run_tag:enable_delay
|
39
|
+
|
40
|
+
- run:
|
41
|
+
name: Run active_record_base specs
|
42
|
+
command: |
|
43
|
+
bundle exec rspec --format progress \
|
44
|
+
--format RspecJunitFormatter \
|
45
|
+
--out /tmp/test-results/rspec-basic.xml \
|
46
|
+
--format progress \
|
47
|
+
spec --tag run_tag:active_record_base
|
48
|
+
|
49
|
+
- run:
|
50
|
+
name: Run application_record specs
|
51
|
+
command: |
|
52
|
+
bundle exec rspec --format progress \
|
53
|
+
--format RspecJunitFormatter \
|
54
|
+
--out /tmp/test-results/rspec-basic.xml \
|
55
|
+
--format progress \
|
56
|
+
spec --tag run_tag:application_record
|
57
|
+
|
58
|
+
- run:
|
59
|
+
name: Run active_record_single specs
|
60
|
+
command: |
|
61
|
+
bundle exec rspec --format progress \
|
62
|
+
--format RspecJunitFormatter \
|
63
|
+
--out /tmp/test-results/rspec-basic.xml \
|
64
|
+
--format progress \
|
65
|
+
spec --tag run_tag:active_record_single
|
66
|
+
|
67
|
+
- run:
|
68
|
+
name: Run action_mailer specs
|
69
|
+
command: |
|
70
|
+
bundle exec rspec --format progress \
|
71
|
+
--format RspecJunitFormatter \
|
72
|
+
--out /tmp/test-results/rspec-basic.xml \
|
73
|
+
--format progress \
|
74
|
+
spec --tag run_tag:action_mailer_base
|
75
|
+
|
76
|
+
- run:
|
77
|
+
name: Run application_mailer specs
|
78
|
+
command: |
|
79
|
+
bundle exec rspec --format progress \
|
80
|
+
--format RspecJunitFormatter \
|
81
|
+
--out /tmp/test-results/rspec-basic.xml \
|
82
|
+
--format progress \
|
83
|
+
spec --tag run_tag:application_mailer
|
84
|
+
- run:
|
85
|
+
name: Run action_mailer_single specs
|
86
|
+
command: |
|
87
|
+
bundle exec rspec --format progress \
|
88
|
+
--format RspecJunitFormatter \
|
89
|
+
--out /tmp/test-results/rspec-basic.xml \
|
90
|
+
--format progress \
|
91
|
+
spec --tag run_tag:action_mailer_single
|
39
92
|
|
40
93
|
# collect reports
|
41
94
|
- store_test_results:
|
data/CHANGELOG.md
ADDED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sidekiq_simple_delay (0.
|
4
|
+
sidekiq_simple_delay (0.2.0)
|
5
5
|
sidekiq
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
+
actionmailer (5.2.1.1)
|
11
|
+
actionpack (= 5.2.1.1)
|
12
|
+
actionview (= 5.2.1.1)
|
13
|
+
activejob (= 5.2.1.1)
|
14
|
+
mail (~> 2.5, >= 2.5.4)
|
15
|
+
rails-dom-testing (~> 2.0)
|
16
|
+
actionpack (5.2.1.1)
|
17
|
+
actionview (= 5.2.1.1)
|
18
|
+
activesupport (= 5.2.1.1)
|
19
|
+
rack (~> 2.0)
|
20
|
+
rack-test (>= 0.6.3)
|
21
|
+
rails-dom-testing (~> 2.0)
|
22
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
23
|
+
actionview (5.2.1.1)
|
24
|
+
activesupport (= 5.2.1.1)
|
25
|
+
builder (~> 3.1)
|
26
|
+
erubi (~> 1.4)
|
27
|
+
rails-dom-testing (~> 2.0)
|
28
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
29
|
+
activejob (5.2.1.1)
|
30
|
+
activesupport (= 5.2.1.1)
|
31
|
+
globalid (>= 0.3.6)
|
10
32
|
activemodel (5.2.1.1)
|
11
33
|
activesupport (= 5.2.1.1)
|
12
34
|
activerecord (5.2.1.1)
|
@@ -20,18 +42,33 @@ GEM
|
|
20
42
|
tzinfo (~> 1.1)
|
21
43
|
arel (9.0.0)
|
22
44
|
ast (2.4.0)
|
45
|
+
builder (3.2.3)
|
23
46
|
bundler-audit (0.6.0)
|
24
47
|
bundler (~> 1.2)
|
25
48
|
thor (~> 0.18)
|
26
49
|
concurrent-ruby (1.1.3)
|
27
50
|
connection_pool (2.2.2)
|
51
|
+
crass (1.0.4)
|
52
|
+
database_cleaner (1.7.0)
|
28
53
|
diff-lcs (1.3)
|
54
|
+
erubi (1.7.1)
|
29
55
|
fakeredis (0.7.0)
|
30
56
|
redis (>= 3.2, < 5.0)
|
57
|
+
globalid (0.4.1)
|
58
|
+
activesupport (>= 4.2.0)
|
31
59
|
i18n (1.1.1)
|
32
60
|
concurrent-ruby (~> 1.0)
|
33
61
|
jaro_winkler (1.5.1)
|
62
|
+
loofah (2.2.3)
|
63
|
+
crass (~> 1.0.2)
|
64
|
+
nokogiri (>= 1.5.9)
|
65
|
+
mail (2.7.1)
|
66
|
+
mini_mime (>= 0.1.1)
|
67
|
+
mini_mime (1.0.1)
|
68
|
+
mini_portile2 (2.3.0)
|
34
69
|
minitest (5.11.3)
|
70
|
+
nokogiri (1.8.5)
|
71
|
+
mini_portile2 (~> 2.3.0)
|
35
72
|
parallel (1.12.1)
|
36
73
|
parser (2.5.3.0)
|
37
74
|
ast (~> 2.4.0)
|
@@ -39,6 +76,13 @@ GEM
|
|
39
76
|
rack (2.0.6)
|
40
77
|
rack-protection (2.0.4)
|
41
78
|
rack
|
79
|
+
rack-test (1.1.0)
|
80
|
+
rack (>= 1.0, < 3)
|
81
|
+
rails-dom-testing (2.0.3)
|
82
|
+
activesupport (>= 4.2.0)
|
83
|
+
nokogiri (>= 1.6)
|
84
|
+
rails-html-sanitizer (1.0.4)
|
85
|
+
loofah (~> 2.2, >= 2.2.2)
|
42
86
|
rainbow (3.0.0)
|
43
87
|
rake (10.5.0)
|
44
88
|
redis (4.0.3)
|
@@ -82,10 +126,12 @@ PLATFORMS
|
|
82
126
|
ruby
|
83
127
|
|
84
128
|
DEPENDENCIES
|
129
|
+
actionmailer (> 3.0)
|
85
130
|
activerecord (> 3.0)
|
86
131
|
activesupport (> 3.0)
|
87
132
|
bundler (~> 1.16)
|
88
133
|
bundler-audit
|
134
|
+
database_cleaner
|
89
135
|
fakeredis
|
90
136
|
rake (~> 10.0)
|
91
137
|
rspec (~> 3.0)
|
data/README.md
CHANGED
@@ -49,6 +49,8 @@ end
|
|
49
49
|
# ...
|
50
50
|
|
51
51
|
User.simple_delay.greeting
|
52
|
+
User.simple_delay_for(10.minutes).greeting
|
53
|
+
User.simple_delay_until(1.day.from_now).greeting
|
52
54
|
```
|
53
55
|
|
54
56
|
To add delay functionality to the instances of a class:
|
@@ -73,6 +75,31 @@ Three methods are provided that map to the three main invocations for Sidekiq.
|
|
73
75
|
* `simple_delay_for` -> `perform_in`
|
74
76
|
* `simple_delay_until` -> `perform_at`
|
75
77
|
|
78
|
+
### Simple Delay Spread
|
79
|
+
|
80
|
+
Often we want to enqueue a bunch of jobs, but need to spread them out over some period of time to prevent swampping our resources. We use a similar API to [`sidekiq_spread`](https://github.com/Latermedia/sidekiq_spread) to evenly distribute job execution.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class User
|
84
|
+
extend SidekiqSimpleDelay::DelayMethods
|
85
|
+
|
86
|
+
def greeting(name)
|
87
|
+
"Hello, #{name}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# ...
|
92
|
+
|
93
|
+
spread_options = {
|
94
|
+
spread_duration: 3.hours,
|
95
|
+
spread_in: 15.minutes
|
96
|
+
}
|
97
|
+
|
98
|
+
# Randomly enqueues a job sometime between 15 minutes and 3 hours
|
99
|
+
# and 15 minutes from now
|
100
|
+
User.simple_delay_spread(spread_options).greeting('Les')
|
101
|
+
```
|
102
|
+
|
76
103
|
### Devops
|
77
104
|
|
78
105
|
A few conveniences are provided that allow you enable this functionality from the command line.
|
@@ -120,7 +147,7 @@ One use case of these methods would be for delaying methods on an `ActiveRecord`
|
|
120
147
|
```ruby
|
121
148
|
class ApplicationRecord < ActiveRecord::Base
|
122
149
|
def initialize_args
|
123
|
-
[
|
150
|
+
[send(self.class.primary_key)]
|
124
151
|
end
|
125
152
|
|
126
153
|
def self.simple_delay_initialize(*args)
|
@@ -144,6 +171,33 @@ User.where(column1: true).find_each do |user|
|
|
144
171
|
end
|
145
172
|
```
|
146
173
|
|
174
|
+
In fact, this is exactly what `sidekiq_delay` does with its `ActiveRecord` integration. To enable it,
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
SidekiqSimpleDelay.enable_delay_active_record!
|
178
|
+
```
|
179
|
+
|
180
|
+
This will try to add the methods to `ApplicationRecord` first if it exists, but falls back to `ActiveRecord::Base` if it doesn't. You can also add it a single class if you want.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
SidekiqSimpleDelay.enable_delay_active_record!(User)
|
184
|
+
```
|
185
|
+
To spread these jobs out over an interval of time:
|
186
|
+
```ruby
|
187
|
+
spread_options = {
|
188
|
+
spread_duration: 8.hours,
|
189
|
+
spread_at: 3.hours.from_now,
|
190
|
+
spread_method: :mod,
|
191
|
+
spread_mod_method: :id
|
192
|
+
}
|
193
|
+
|
194
|
+
User.where(column1: true).find_each do |user|
|
195
|
+
user.simple_delay_spread(spread_options).long_running_user_task('things')
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
199
|
+
By modding on the id of the `User` object, we can be sure that if we run this script with the same options, each user job will be executed at about the same relative time. This is useful if you have recurring jobs where having a deterministic offset for a user is beneficial.
|
200
|
+
|
147
201
|
### Simple Objects
|
148
202
|
|
149
203
|
`SidekiqSimpleDelay` only allows simple objects to be used as parameters to the delayed method. These objects are:
|
data/lib/sidekiq_simple_delay.rb
CHANGED
@@ -9,20 +9,90 @@ module SidekiqSimpleDelay
|
|
9
9
|
# Adds simple_delay class methods to all classes
|
10
10
|
def enable_delay!
|
11
11
|
enable_delay_instance!(Module)
|
12
|
+
|
13
|
+
return unless defined?(::ActiveSupport)
|
14
|
+
|
15
|
+
ActiveSupport.on_load(:active_record) do
|
16
|
+
SidekiqSimpleDelay.enable_delay_active_record!
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveSupport.on_load(:action_mailer) do
|
20
|
+
SidekiqSimpleDelay.enable_delay_application_mailer!
|
21
|
+
end
|
12
22
|
end
|
13
23
|
|
14
|
-
# Adds simple_delay class methods to
|
24
|
+
# Adds simple_delay class methods to a class
|
25
|
+
#
|
26
|
+
# @param klass [Class] Class to add simple_delay class methods to
|
15
27
|
def enable_delay_class!(klass)
|
16
28
|
raise ArgumentError, 'klass must be a Class' unless klass.class.is_a?(Class)
|
17
29
|
|
30
|
+
return if klass.singleton_class.included_modules.include?(SidekiqSimpleDelay::DelayMethods)
|
31
|
+
|
18
32
|
klass.__send__(:extend, SidekiqSimpleDelay::DelayMethods)
|
19
33
|
end
|
20
34
|
|
21
|
-
# Adds simple_delay instance methods to
|
35
|
+
# Adds simple_delay instance methods to class
|
36
|
+
#
|
37
|
+
# @param klass [Class] Class to add simple_delay instance methods to
|
22
38
|
def enable_delay_instance!(klass)
|
23
39
|
raise ArgumentError, 'klass must be a Class' unless klass.class.is_a?(Class)
|
24
40
|
|
41
|
+
return if klass.included_modules.include?(SidekiqSimpleDelay::DelayMethods)
|
42
|
+
|
25
43
|
klass.__send__(:include, SidekiqSimpleDelay::DelayMethods)
|
26
44
|
end
|
45
|
+
|
46
|
+
# Adds simple_delay functionality to ActiveRecord objects. Attempts to add to {ApplicationRecord} first,
|
47
|
+
# the falls back to adding to {ActiveRecord::Base}.
|
48
|
+
#
|
49
|
+
# @param klass [Class] Class to add simple_delay functionality to. Must inherit from {ActiveRecord::Base}.
|
50
|
+
def enable_delay_active_record!(klass = nil)
|
51
|
+
klass =
|
52
|
+
if !klass.nil?
|
53
|
+
klass
|
54
|
+
elsif defined?(::ApplicationRecord)
|
55
|
+
::ApplicationRecord
|
56
|
+
elsif defined?(::ActiveRecord::Base)
|
57
|
+
::ActiveRecord::Base
|
58
|
+
end
|
59
|
+
|
60
|
+
raise ArgumentError, 'klass must be supplied' if klass.nil?
|
61
|
+
raise ArgumentError, 'klass must be a class' unless klass.class.is_a?(Class)
|
62
|
+
raise ArgumentError, 'klass must inherit from ActiveRecord::Base' unless klass.ancestors.any? { |c| c.name == 'ActiveRecord::Base' }
|
63
|
+
|
64
|
+
ar_file = 'sidekiq_simple_delay/extensions/active_record'
|
65
|
+
require ar_file unless defined? SidekiqSimpleDelay::ActiveRecord
|
66
|
+
|
67
|
+
return if klass.included_modules.include?(SidekiqSimpleDelay::ActiveRecord)
|
68
|
+
|
69
|
+
klass.__send__(:include, SidekiqSimpleDelay::ActiveRecord)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adds simple_delay functionality to ActionMailer objects. Attempts to add to {ApplicationMailer} first,
|
73
|
+
# the falls back to adding to {ActionMailer::Base}.
|
74
|
+
#
|
75
|
+
# @param klass [Class] Class to add simple_delay functionality to. Must inherit from {ActionMailer::Base}.
|
76
|
+
def enable_delay_application_mailer!(klass = nil)
|
77
|
+
klass =
|
78
|
+
if !klass.nil?
|
79
|
+
klass
|
80
|
+
elsif defined?(::ApplicationMailer)
|
81
|
+
::ApplicationMailer
|
82
|
+
elsif defined?(::ActionMailer::Base)
|
83
|
+
::ActionMailer::Base
|
84
|
+
end
|
85
|
+
|
86
|
+
raise ArgumentError, 'klass must be supplied' if klass.nil?
|
87
|
+
raise ArgumentError, 'klass must be a class' unless klass.class.is_a?(Class)
|
88
|
+
raise ArgumentError, 'klass must inherit from ActionMailer::Base' unless klass.ancestors.any? { |c| c.name == 'ActionMailer::Base' }
|
89
|
+
|
90
|
+
ar_file = 'sidekiq_simple_delay/extensions/action_mailer'
|
91
|
+
require ar_file unless defined? SidekiqSimpleDelay::ActionMailer
|
92
|
+
|
93
|
+
return if klass.included_modules.include?(SidekiqSimpleDelay::ActionMailer)
|
94
|
+
|
95
|
+
klass.__send__(:include, SidekiqSimpleDelay::ActionMailer)
|
96
|
+
end
|
27
97
|
end
|
28
98
|
end
|
@@ -2,24 +2,113 @@
|
|
2
2
|
|
3
3
|
require 'sidekiq_simple_delay/delay_worker'
|
4
4
|
require 'sidekiq_simple_delay/generic_proxy'
|
5
|
+
require 'sidekiq_simple_delay/utils'
|
5
6
|
|
6
7
|
module SidekiqSimpleDelay
|
7
8
|
# Aliased class methods to be added to Class
|
8
9
|
module DelayMethods
|
10
|
+
# Immediately enqueue a job to handle the delayed action
|
11
|
+
#
|
12
|
+
# @param options [Hash] options similar to Sidekiq's `perform_async`
|
9
13
|
def simple_sidekiq_delay(options = {})
|
10
|
-
Proxy.new(
|
14
|
+
Proxy.new(simple_delayed_worker, self, options)
|
11
15
|
end
|
12
16
|
|
17
|
+
# Enqueue a job to handle the delayed action after an elapsed interval
|
18
|
+
#
|
19
|
+
# @param interval [#to_f] Number of seconds to wait. `to_f` will be called on
|
20
|
+
# this argument to convert to seconds.
|
21
|
+
# @param options [Hash] options similar to Sidekiq's `perform_in`
|
13
22
|
def simple_sidekiq_delay_for(interval, options = {})
|
14
|
-
Proxy.new(
|
23
|
+
Proxy.new(simple_delayed_worker, self, options.merge('at' => Time.now.to_f + interval.to_f))
|
15
24
|
end
|
16
25
|
|
26
|
+
# Enqueue a job to handle the delayed action after at a certain time
|
27
|
+
#
|
28
|
+
# @param timestamp [#to_f] Timestamp to execute job at. `to_f` will be called on
|
29
|
+
# this argument to convert to a timestamp.
|
30
|
+
# @param options [Hash] options similar to Sidekiq's `perform_at`
|
17
31
|
def simple_sidekiq_delay_until(timestamp, options = {})
|
18
|
-
Proxy.new(
|
32
|
+
Proxy.new(simple_delayed_worker, self, options.merge('at' => timestamp.to_f))
|
33
|
+
end
|
34
|
+
|
35
|
+
# Enqueue a job to handle the delayed action in a given timeframe
|
36
|
+
#
|
37
|
+
# @param timestamp [#to_f] Timestamp to execute job at. `to_f` will be called on
|
38
|
+
# this argument to convert to a timestamp.
|
39
|
+
# @param options [Hash] options similar to Sidekiq's `perform_at`
|
40
|
+
# @option options [Number] :spread_duration Size of window to spread workers out over
|
41
|
+
# @option options [Number] :spread_in Start of window offset from now
|
42
|
+
# @option options [Number] :spread_at Start of window offset timestamp
|
43
|
+
# @option options [rand|mod] :spread_method perform either a random or modulo spread,
|
44
|
+
# default: *:rand*
|
45
|
+
# @option options [Number] :spread_mod_value value to use for determining mod offset
|
46
|
+
# @option options [Symbol] :spread_mod_method method to call to get the value to use
|
47
|
+
# for determining mod offset
|
48
|
+
def simple_sidekiq_delay_spread(options = {})
|
49
|
+
spread_duration = Utils.extract_option(options, :spread_duration, 1.hour).to_f
|
50
|
+
spread_in = Utils.extract_option(options, :spread_in, 0).to_f
|
51
|
+
spread_at = Utils.extract_option(options, :spread_at)
|
52
|
+
spread_method = Utils.extract_option(options, :spread_method, :rand)
|
53
|
+
spread_mod_value = Utils.extract_option(options, :spread_mod_value)
|
54
|
+
spread_mod_method = Utils.extract_option(options, :spread_mod_method)
|
55
|
+
|
56
|
+
spread_duration = 0 if spread_duration < 0
|
57
|
+
spread_in = 0 if spread_in < 0
|
58
|
+
|
59
|
+
spread =
|
60
|
+
# kick of immediately if the duration is 0
|
61
|
+
if spread_duration.zero?
|
62
|
+
0
|
63
|
+
else
|
64
|
+
case spread_method.to_sym
|
65
|
+
when :rand
|
66
|
+
Utils.random_number(spread_duration)
|
67
|
+
when :mod
|
68
|
+
mod_value =
|
69
|
+
# The mod value has been supplied
|
70
|
+
if !spread_mod_value.nil?
|
71
|
+
spread_mod_value
|
72
|
+
# Call the supplied method on the target object to get mod value
|
73
|
+
elsif !spread_mod_method.nil?
|
74
|
+
send(spread_mod_method)
|
75
|
+
# Call `spread_mod_method` on target object to get mod value
|
76
|
+
elsif respond_to?(:spread_mod_method)
|
77
|
+
send(send(:spread_mod_method))
|
78
|
+
else
|
79
|
+
raise ArgumentError, 'must specify `spread_mod_value` or `spread_mod_method` or taget must respond to `spread_mod_method`'
|
80
|
+
end
|
81
|
+
|
82
|
+
# calculate the mod based offset
|
83
|
+
mod_value % spread_duration
|
84
|
+
else
|
85
|
+
raise ArgumentError, "spread_method must :rand or :mod, `#{spread_method} is invalid`"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
t =
|
90
|
+
if !spread_at.nil?
|
91
|
+
# add spread to a timestamp
|
92
|
+
spread_at.to_f + spread
|
93
|
+
elsif !spread_in.nil?
|
94
|
+
# add spread to no plus constant offset
|
95
|
+
Time.now.to_f + spread_in.to_f + spread
|
96
|
+
else
|
97
|
+
# add spread to current time
|
98
|
+
Time.now.to_f + spread
|
99
|
+
end
|
100
|
+
|
101
|
+
Proxy.new(SimpleDelayedWorker, self, options.merge('at' => t))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Tell {DelayMethods} which delayed worker to use
|
105
|
+
def simple_delayed_worker
|
106
|
+
SimpleDelayedWorker
|
19
107
|
end
|
20
108
|
|
21
109
|
alias simple_delay simple_sidekiq_delay
|
22
110
|
alias simple_delay_for simple_sidekiq_delay_for
|
23
111
|
alias simple_delay_until simple_sidekiq_delay_until
|
112
|
+
alias simple_delay_spread simple_sidekiq_delay_spread
|
24
113
|
end
|
25
114
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'sidekiq'
|
4
|
-
require 'sidekiq_simple_delay/generic_proxy'
|
5
4
|
|
6
5
|
module SidekiqSimpleDelay
|
7
|
-
# Worker that handles the
|
6
|
+
# Worker that handles the simple_delayed functionality
|
8
7
|
class SimpleDelayedWorker
|
9
8
|
include Sidekiq::Worker
|
10
9
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sidekiq'
|
4
|
+
|
5
|
+
module SidekiqSimpleDelay
|
6
|
+
# Worker that handles the simple_delayed functionality for ActionMailers
|
7
|
+
class SimpleDelayedMailer
|
8
|
+
include Sidekiq::Worker
|
9
|
+
|
10
|
+
def perform(args)
|
11
|
+
target_klass = Object.const_get(args.fetch('target_klass'))
|
12
|
+
|
13
|
+
method_name = args['m']
|
14
|
+
method_args = args['args']
|
15
|
+
|
16
|
+
msg = target_klass.__send__(method_name, *method_args)
|
17
|
+
|
18
|
+
# The email method can return nil, which causes ActionMailer to return
|
19
|
+
# an undeliverable empty message.
|
20
|
+
raise "#{target.name}##{method_name} returned an undeliverable mail object" unless msg
|
21
|
+
|
22
|
+
deliver(msg)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def deliver(msg)
|
28
|
+
if msg.respond_to?(:deliver_now)
|
29
|
+
# Rails 4.2/5.0
|
30
|
+
msg.deliver_now
|
31
|
+
else
|
32
|
+
# Rails 3.2/4.0/4.1
|
33
|
+
msg.deliver
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sidekiq_simple_delay/delay_methods'
|
4
|
+
require 'sidekiq_simple_delay/delayed_mailer'
|
5
|
+
|
6
|
+
module SidekiqSimpleDelay
|
7
|
+
# Methods to enable simple_delay functionality to work with ActiveRecord
|
8
|
+
module ActionMailer
|
9
|
+
def self.included(base)
|
10
|
+
base.extend(SidekiqSimpleDelay::DelayMethods)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Tell {DelayMethods} which delayed worker to use
|
15
|
+
module ClassMethods
|
16
|
+
def simple_delayed_worker
|
17
|
+
SimpleDelayedMailer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sidekiq_simple_delay/delay_methods'
|
4
|
+
|
5
|
+
module SidekiqSimpleDelay
|
6
|
+
# Methods to enable simple_delay functionality to work with ActiveRecord
|
7
|
+
module ActiveRecord
|
8
|
+
def self.included(base)
|
9
|
+
base.include(SidekiqSimpleDelay::DelayMethods)
|
10
|
+
base.extend(SidekiqSimpleDelay::DelayMethods)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Args required to fetch this object from the database
|
15
|
+
def initialize_args
|
16
|
+
[send(self.class.primary_key)]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Class methods to enable simple_delay functionality to work with ActiveRecord
|
20
|
+
module ClassMethods
|
21
|
+
# Take delay worker args and fetch record from database
|
22
|
+
def simple_delay_initialize(*args)
|
23
|
+
find(args[0])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -30,6 +30,7 @@ module SidekiqSimpleDelay
|
|
30
30
|
Set.new([Fixnum, Bignum, Float]).freeze
|
31
31
|
end
|
32
32
|
|
33
|
+
# @private
|
33
34
|
def simple_object?(obj)
|
34
35
|
klass = obj.class
|
35
36
|
|
@@ -43,6 +44,27 @@ module SidekiqSimpleDelay
|
|
43
44
|
false
|
44
45
|
end
|
45
46
|
end
|
47
|
+
|
48
|
+
# @private
|
49
|
+
def extract_option(opts, arg, default = nil)
|
50
|
+
[arg.to_sym, arg.to_s].each do |a|
|
51
|
+
next unless opts.key?(a)
|
52
|
+
|
53
|
+
return opts.delete(a)
|
54
|
+
end
|
55
|
+
|
56
|
+
default
|
57
|
+
end
|
58
|
+
|
59
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0')
|
60
|
+
def random_number(duration)
|
61
|
+
SecureRandom.random_number(duration)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
def random_number(duration)
|
65
|
+
rand * duration
|
66
|
+
end
|
67
|
+
end
|
46
68
|
end
|
47
69
|
end
|
48
70
|
end
|
data/run_specs
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
|
-
bundle exec rspec spec --tag ~
|
4
|
-
bundle exec rspec spec --tag enable_delay
|
3
|
+
bundle exec rspec spec --tag ~run_tag
|
4
|
+
bundle exec rspec spec --tag run_tag:enable_delay
|
5
|
+
bundle exec rspec spec --tag run_tag:active_record_base
|
6
|
+
bundle exec rspec spec --tag run_tag:application_record
|
7
|
+
bundle exec rspec spec --tag run_tag:active_record_single
|
8
|
+
bundle exec rspec spec --tag run_tag:action_mailer_base
|
9
|
+
bundle exec rspec spec --tag run_tag:application_mailer
|
10
|
+
bundle exec rspec spec --tag run_tag:action_mailer_single
|
@@ -24,10 +24,12 @@ Gem::Specification.new do |spec|
|
|
24
24
|
|
25
25
|
spec.add_dependency('sidekiq')
|
26
26
|
|
27
|
+
spec.add_development_dependency 'actionmailer', '> 3.0'
|
27
28
|
spec.add_development_dependency 'activerecord', '> 3.0'
|
28
29
|
spec.add_development_dependency 'activesupport', '> 3.0'
|
29
30
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
30
31
|
spec.add_development_dependency 'bundler-audit'
|
32
|
+
spec.add_development_dependency 'database_cleaner'
|
31
33
|
spec.add_development_dependency 'fakeredis'
|
32
34
|
spec.add_development_dependency 'rake', '~> 10.0'
|
33
35
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq_simple_delay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Les Fletcher
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionmailer
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: activerecord
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: database_cleaner
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: fakeredis
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -189,6 +217,7 @@ files:
|
|
189
217
|
- ".gitignore"
|
190
218
|
- ".rspec"
|
191
219
|
- ".rubocop.yml"
|
220
|
+
- CHANGELOG.md
|
192
221
|
- CODE_OF_CONDUCT.md
|
193
222
|
- Gemfile
|
194
223
|
- Gemfile.lock
|
@@ -200,6 +229,9 @@ files:
|
|
200
229
|
- lib/sidekiq_simple_delay.rb
|
201
230
|
- lib/sidekiq_simple_delay/delay_methods.rb
|
202
231
|
- lib/sidekiq_simple_delay/delay_worker.rb
|
232
|
+
- lib/sidekiq_simple_delay/delayed_mailer.rb
|
233
|
+
- lib/sidekiq_simple_delay/extensions/action_mailer.rb
|
234
|
+
- lib/sidekiq_simple_delay/extensions/active_record.rb
|
203
235
|
- lib/sidekiq_simple_delay/generic_proxy.rb
|
204
236
|
- lib/sidekiq_simple_delay/utils.rb
|
205
237
|
- lib/sidekiq_simple_delay/version.rb
|