sucker_punch 2.0.1 → 3.0.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 +5 -5
- data/.travis.yml +2 -1
- data/CHANGES.md +46 -0
- data/README.md +36 -8
- data/lib/generators/sucker_punch/templates/job.rb +2 -2
- data/lib/sucker_punch.rb +10 -10
- data/lib/sucker_punch/async_syntax.rb +2 -3
- data/lib/sucker_punch/job.rb +21 -12
- data/lib/sucker_punch/queue.rb +50 -37
- data/lib/sucker_punch/testing.rb +44 -0
- data/lib/sucker_punch/testing/inline.rb +5 -5
- data/lib/sucker_punch/version.rb +1 -1
- data/sucker_punch.gemspec +9 -3
- data/test/sucker_punch/job_test.rb +5 -1
- data/test/sucker_punch/queue_test.rb +15 -14
- data/test/sucker_punch_test.rb +1 -1
- metadata +15 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e1edad787473a077f23f2fae95150cdb92e3834a12150fbd4d910fade5692516
|
4
|
+
data.tar.gz: 4ba7b7fa6cf3a1c99706a3bda43b0fd2fc291ae1825a23466b00a5b7a3354003
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8184cafe29937ad818920951c3c760e8435b4e35a348e27629053bae1b56e2f44ab412154fb3769e6878034a9351ad5e60fb44d9385bf5bb4f2bf58cc91c71c
|
7
|
+
data.tar.gz: fde16057612312085f59a955e783007b6a0cf0b4ff7d08312963bc0c76b3be2e5d254e5eb1df1625db3c554403485e5df8a1c995ab50b71dda4e1358b00e8d23
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,49 @@
|
|
1
|
+
3.0.0
|
2
|
+
-------
|
3
|
+
- Add support for keyword arguments in ruby `>= 3.0`. More details in [release notes](https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/).
|
4
|
+
|
5
|
+
2.1.1
|
6
|
+
-------
|
7
|
+
- Relax versioning constraint of `concurrent-ruby` to make way for 1.1 release
|
8
|
+
|
9
|
+
2.1.0
|
10
|
+
-------
|
11
|
+
- Add `max_jobs` configuration option to set the maximum number of tasks that
|
12
|
+
may be waiting in the work queue
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
class JobWithLimit
|
16
|
+
include SuckerPunch::Job
|
17
|
+
max_jobs 2
|
18
|
+
|
19
|
+
def perform(data)
|
20
|
+
# work...
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
10.times do
|
25
|
+
begin
|
26
|
+
JobWithLimit.perform_async('work') }
|
27
|
+
rescue Concurrent::RejectedExecutionError => e
|
28
|
+
# Queue maxed out, this job didn't get queued
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
2.0.4
|
33
|
+
-------
|
34
|
+
- Better initialization of variables and names to remove warnings
|
35
|
+
|
36
|
+
2.0.3
|
37
|
+
-------
|
38
|
+
- Rewrite shutdown strategy to fix bug related to premature shutdown when only
|
39
|
+
1 job is in enqueued when a job has more than 1 worker
|
40
|
+
|
41
|
+
2.0.2
|
42
|
+
-------
|
43
|
+
- Don't consider global shutdown bool when exhausting the queue during
|
44
|
+
shutdown. This led to `shutdown_timeout` not being respected when
|
45
|
+
processing remaining jobs left in the queue with a high `shutdown_timeout`.
|
46
|
+
|
1
47
|
2.0.1
|
2
48
|
-------
|
3
49
|
- Remove scripts from `bin/`
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Sucker Punch
|
2
2
|
|
3
|
-
[](https://travis-ci.org/brandonhilkert/sucker_punch)
|
4
|
+
[](https://codeclimate.com/github/brandonhilkert/sucker_punch)
|
5
5
|
|
6
6
|
Sucker Punch is a single-process Ruby asynchronous processing library.
|
7
7
|
This reduces costs
|
@@ -14,8 +14,7 @@ crunching, or social platform manipulation. No reason to hold up a
|
|
14
14
|
user when you can do these things in the background within the same
|
15
15
|
process as your web application...
|
16
16
|
|
17
|
-
Sucker Punch is built on top of [concurrent-ruby]
|
18
|
-
(https://github.com/ruby-concurrency/concurrent-ruby). Each job is setup as
|
17
|
+
Sucker Punch is built on top of [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby). Each job is setup as
|
19
18
|
a pool, which equates to its own queue with individual workers working against
|
20
19
|
the jobs. Unlike most other background processing libraries, Sucker
|
21
20
|
Punch's jobs are stored in memory. The benefit to this is there is no
|
@@ -115,6 +114,22 @@ class LogJob
|
|
115
114
|
end
|
116
115
|
```
|
117
116
|
|
117
|
+
#### Configure the Queue Size
|
118
|
+
|
119
|
+
The default number of jobs that can be queued is unlimited. If you wish to restrict this you can set
|
120
|
+
max\_jobs as follows:
|
121
|
+
|
122
|
+
```Ruby
|
123
|
+
class LogJob
|
124
|
+
include SuckerPunch::Job
|
125
|
+
max_jobs 10
|
126
|
+
|
127
|
+
def perform(event)
|
128
|
+
Log.new(event).track
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
118
133
|
#### Executing Jobs in the Future
|
119
134
|
|
120
135
|
Many background processing libraries have methods to perform operations after a
|
@@ -132,7 +147,7 @@ class DataJob
|
|
132
147
|
end
|
133
148
|
|
134
149
|
DataJob.perform_async("asdf") # immediately perform asynchronously
|
135
|
-
DataJob.perform_in(60, "asdf") # `perform` will be
|
150
|
+
DataJob.perform_in(60, "asdf") # `perform` will be executed 60 sec. later
|
136
151
|
```
|
137
152
|
|
138
153
|
#### `ActiveRecord` Connection Pool Connections
|
@@ -255,6 +270,19 @@ $ rails g sucker_punch:job logger
|
|
255
270
|
would create the file `app/jobs/logger_job.rb` with a unimplemented `#perform`
|
256
271
|
method.
|
257
272
|
|
273
|
+
## Sinatra
|
274
|
+
|
275
|
+
If you're using Sucker Punch with Sinatra, you must require Sucker Punch before Sinatra:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
# app.rb
|
279
|
+
|
280
|
+
require 'sucker_punch'
|
281
|
+
require 'sinatra'
|
282
|
+
```
|
283
|
+
|
284
|
+
This will ensure Sucker Punch's `at_exit()` handler to clean up and shutdown queues does not happen **before** Sinatra *starts up* via its own `at_exit()` handler.
|
285
|
+
|
258
286
|
## Active Job
|
259
287
|
|
260
288
|
Sucker Punch has been added as an Active Job adapter in Rails 4.2.
|
@@ -270,11 +298,11 @@ gem 'sucker_punch'
|
|
270
298
|
And then configure the backend to use Sucker Punch:
|
271
299
|
|
272
300
|
```Ruby
|
273
|
-
# config/
|
274
|
-
Rails
|
301
|
+
# config/application.rb
|
302
|
+
class Application < Rails::Application
|
303
|
+
# ...
|
275
304
|
config.active_job.queue_adapter = :sucker_punch
|
276
305
|
end
|
277
|
-
|
278
306
|
```
|
279
307
|
|
280
308
|
If you want to use Sucker Punch version `2.0.0+` with Rails `< 5.0.0`, be sure
|
data/lib/sucker_punch.rb
CHANGED
@@ -10,12 +10,12 @@ module SuckerPunch
|
|
10
10
|
RUNNING = Concurrent::AtomicBoolean.new(true)
|
11
11
|
|
12
12
|
class << self
|
13
|
-
def exception_handler
|
14
|
-
@exception_handler
|
13
|
+
def exception_handler
|
14
|
+
@exception_handler ||= method(:default_exception_handler)
|
15
15
|
end
|
16
16
|
|
17
|
-
def exception_handler
|
18
|
-
@exception_handler
|
17
|
+
def exception_handler=(handler)
|
18
|
+
@exception_handler = handler
|
19
19
|
end
|
20
20
|
|
21
21
|
def default_exception_handler(ex, klass, args)
|
@@ -26,11 +26,7 @@ module SuckerPunch
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def logger
|
29
|
-
@logger
|
30
|
-
end
|
31
|
-
|
32
|
-
def logger=(log)
|
33
|
-
@logger = (log ? log : Logger.new('/dev/null'))
|
29
|
+
@logger ||= default_logger
|
34
30
|
end
|
35
31
|
|
36
32
|
def default_logger
|
@@ -39,9 +35,13 @@ module SuckerPunch
|
|
39
35
|
l
|
40
36
|
end
|
41
37
|
|
38
|
+
def logger=(log)
|
39
|
+
@logger = (log ? log : Logger.new('/dev/null'))
|
40
|
+
end
|
41
|
+
|
42
42
|
def shutdown_timeout
|
43
43
|
# 10 seconds on heroku, minus a grace period
|
44
|
-
@shutdown_timeout
|
44
|
+
@shutdown_timeout ||= 8
|
45
45
|
end
|
46
46
|
|
47
47
|
def shutdown_timeout=(timeout)
|
data/lib/sucker_punch/job.rb
CHANGED
@@ -14,15 +14,17 @@ module SuckerPunch
|
|
14
14
|
# To trigger asynchronous job:
|
15
15
|
#
|
16
16
|
# LogJob.perform_async(1, 2, 3)
|
17
|
-
# LogJob.perform_in(60, 1, 2, 3) # `perform` will be
|
17
|
+
# LogJob.perform_in(60, 1, 2, 3) # `perform` will be executed 60 sec. later
|
18
18
|
#
|
19
19
|
# Note that perform_async is a class method, perform is an instance method.
|
20
20
|
module Job
|
21
21
|
def self.included(base)
|
22
22
|
base.extend(ClassMethods)
|
23
23
|
base.class_attribute :num_workers
|
24
|
+
base.class_attribute :num_jobs_max
|
24
25
|
|
25
26
|
base.num_workers = 2
|
27
|
+
base.num_jobs_max = nil
|
26
28
|
end
|
27
29
|
|
28
30
|
def logger
|
@@ -30,17 +32,17 @@ module SuckerPunch
|
|
30
32
|
end
|
31
33
|
|
32
34
|
module ClassMethods
|
33
|
-
def perform_async(*args)
|
35
|
+
def perform_async(*args, **kwargs)
|
34
36
|
return unless SuckerPunch::RUNNING.true?
|
35
|
-
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers)
|
36
|
-
queue.post
|
37
|
+
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
|
38
|
+
queue.post { __run_perform(*args, **kwargs) }
|
37
39
|
end
|
38
40
|
|
39
|
-
def perform_in(interval, *args)
|
41
|
+
def perform_in(interval, *args, **kwargs)
|
40
42
|
return unless SuckerPunch::RUNNING.true?
|
41
|
-
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers)
|
43
|
+
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
|
42
44
|
job = Concurrent::ScheduledTask.execute(interval.to_f, args: args, executor: queue) do
|
43
|
-
__run_perform(*args)
|
45
|
+
__run_perform(*args, **kwargs)
|
44
46
|
end
|
45
47
|
job.pending?
|
46
48
|
end
|
@@ -49,17 +51,24 @@ module SuckerPunch
|
|
49
51
|
self.num_workers = num
|
50
52
|
end
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
54
|
+
def max_jobs(num)
|
55
|
+
self.num_jobs_max = num
|
56
|
+
end
|
55
57
|
|
58
|
+
def __run_perform(*args, **kwargs)
|
56
59
|
SuckerPunch::Counter::Busy.new(self.to_s).increment
|
57
|
-
|
60
|
+
|
61
|
+
result = if RUBY_VERSION >= '2.5'
|
62
|
+
self.new.perform(*args, **kwargs)
|
63
|
+
else
|
64
|
+
self.new.perform(*args, *(kwargs.any? ? [kwargs] : nil))
|
65
|
+
end
|
66
|
+
|
58
67
|
SuckerPunch::Counter::Processed.new(self.to_s).increment
|
59
68
|
result
|
60
69
|
rescue => ex
|
61
70
|
SuckerPunch::Counter::Failed.new(self.to_s).increment
|
62
|
-
SuckerPunch.exception_handler.call(ex, self, args)
|
71
|
+
SuckerPunch.exception_handler.call(ex, self, [*args, **kwargs])
|
63
72
|
ensure
|
64
73
|
SuckerPunch::Counter::Busy.new(self.to_s).decrement
|
65
74
|
end
|
data/lib/sucker_punch/queue.rb
CHANGED
@@ -5,23 +5,26 @@ module SuckerPunch
|
|
5
5
|
extend Forwardable
|
6
6
|
include Concurrent::ExecutorService
|
7
7
|
|
8
|
+
DEFAULT_MAX_QUEUE_SIZE = 0 # Unlimited
|
9
|
+
|
8
10
|
DEFAULT_EXECUTOR_OPTIONS = {
|
9
11
|
min_threads: 2,
|
10
12
|
max_threads: 2,
|
11
13
|
idletime: 60, # 1 minute
|
12
|
-
max_queue: 0, # unlimited
|
13
14
|
auto_terminate: false # Let shutdown modes handle thread termination
|
14
15
|
}.freeze
|
15
16
|
|
16
17
|
QUEUES = Concurrent::Map.new
|
17
18
|
|
18
|
-
def self.find_or_create(name, num_workers = 2)
|
19
|
+
def self.find_or_create(name, num_workers = 2, num_jobs_max = nil)
|
19
20
|
pool = QUEUES.fetch_or_store(name) do
|
20
|
-
options = DEFAULT_EXECUTOR_OPTIONS
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
options = DEFAULT_EXECUTOR_OPTIONS
|
22
|
+
.merge(
|
23
|
+
min_threads: num_workers,
|
24
|
+
max_threads: num_workers,
|
25
|
+
max_queue: num_jobs_max || DEFAULT_MAX_QUEUE_SIZE
|
26
|
+
)
|
27
|
+
Concurrent::ThreadPoolExecutor.new(**options)
|
25
28
|
end
|
26
29
|
|
27
30
|
new(name, pool)
|
@@ -66,21 +69,43 @@ module SuckerPunch
|
|
66
69
|
queues
|
67
70
|
end
|
68
71
|
|
72
|
+
PAUSE_TIME = STDOUT.tty? ? 0.1 : 0.5
|
73
|
+
|
69
74
|
def self.shutdown_all
|
75
|
+
deadline = Time.now + SuckerPunch.shutdown_timeout
|
76
|
+
|
70
77
|
if SuckerPunch::RUNNING.make_false
|
78
|
+
# If a job is enqueued right before the script exits
|
79
|
+
# (command line, rake task, etc.), the system needs an
|
80
|
+
# interval to allow the enqueue jobs to make it in to the system
|
81
|
+
# otherwise the queue will look idle
|
82
|
+
sleep PAUSE_TIME
|
71
83
|
|
72
84
|
queues = all
|
73
|
-
latch = Concurrent::CountDownLatch.new(queues.length)
|
74
85
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
86
|
+
# Issue shutdown to each queue and let them wrap up their work. This
|
87
|
+
# prevents new jobs from being enqueued and lets the pool clean up
|
88
|
+
# after itself
|
89
|
+
queues.each { |queue| queue.shutdown }
|
90
|
+
|
91
|
+
# return if every queue is empty and workers in every queue are idle
|
92
|
+
return if queues.all? { |queue| queue.idle? }
|
93
|
+
|
94
|
+
SuckerPunch.logger.info("Pausing to allow workers to finish...")
|
79
95
|
|
80
|
-
|
81
|
-
|
82
|
-
|
96
|
+
remaining = deadline - Time.now
|
97
|
+
|
98
|
+
# Continue to loop through each queue and test if it's idle, while
|
99
|
+
# respecting the shutdown timeout
|
100
|
+
while remaining > PAUSE_TIME
|
101
|
+
return if queues.all? { |queue| queue.idle? }
|
102
|
+
sleep PAUSE_TIME
|
103
|
+
remaining = deadline - Time.now
|
83
104
|
end
|
105
|
+
|
106
|
+
# Queues haven't finished work. Aggressively kill them.
|
107
|
+
SuckerPunch.logger.warn("Queued jobs didn't finish before shutdown_timeout...killing remaining jobs")
|
108
|
+
queues.each { |queue| queue.kill }
|
84
109
|
end
|
85
110
|
end
|
86
111
|
|
@@ -89,6 +114,7 @@ module SuckerPunch
|
|
89
114
|
def_delegators :@pool,
|
90
115
|
:max_length,
|
91
116
|
:min_length,
|
117
|
+
:max_queue,
|
92
118
|
:length,
|
93
119
|
:queue_length,
|
94
120
|
:wait_for_termination#,
|
@@ -115,6 +141,10 @@ module SuckerPunch
|
|
115
141
|
synchronize { @running }
|
116
142
|
end
|
117
143
|
|
144
|
+
def idle?
|
145
|
+
enqueued_jobs == 0 && busy_workers == 0
|
146
|
+
end
|
147
|
+
|
118
148
|
def ==(other)
|
119
149
|
pool == other.pool
|
120
150
|
end
|
@@ -135,10 +165,10 @@ module SuckerPunch
|
|
135
165
|
SuckerPunch::Counter::Failed.new(name).value
|
136
166
|
end
|
137
167
|
|
138
|
-
def post(*args, &block)
|
168
|
+
def post(*args, **kwargs, &block)
|
139
169
|
synchronize do
|
140
170
|
if @running
|
141
|
-
@pool.post(*args, &block)
|
171
|
+
@pool.post(*args, **kwargs, &block)
|
142
172
|
else
|
143
173
|
false
|
144
174
|
end
|
@@ -146,15 +176,12 @@ module SuckerPunch
|
|
146
176
|
end
|
147
177
|
|
148
178
|
def kill
|
149
|
-
|
150
|
-
@pool.kill
|
151
|
-
end
|
179
|
+
@pool.kill
|
152
180
|
end
|
153
181
|
|
154
182
|
def shutdown
|
155
|
-
|
156
|
-
|
157
|
-
end
|
183
|
+
synchronize { @running = false }
|
184
|
+
@pool.shutdown
|
158
185
|
end
|
159
186
|
|
160
187
|
protected
|
@@ -162,19 +189,5 @@ module SuckerPunch
|
|
162
189
|
def pool
|
163
190
|
@pool
|
164
191
|
end
|
165
|
-
|
166
|
-
private
|
167
|
-
|
168
|
-
def can_initiate_shutdown?
|
169
|
-
synchronize do
|
170
|
-
if @running
|
171
|
-
@running = false
|
172
|
-
true
|
173
|
-
else
|
174
|
-
false
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
192
|
end
|
179
193
|
end
|
180
|
-
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'sucker_punch'
|
2
|
+
|
3
|
+
# Include this in your tests to simulate
|
4
|
+
# a fake job queue. Jobs won't be executed
|
5
|
+
# as they normal would be the thread pool.
|
6
|
+
# They'll instead be pushed to a fake queue
|
7
|
+
# to be checked in a test environment.
|
8
|
+
#
|
9
|
+
# Include in your test_helper.rb:
|
10
|
+
#
|
11
|
+
# require 'sucker_punch/testing'
|
12
|
+
#
|
13
|
+
# In your application code:
|
14
|
+
#
|
15
|
+
# LogJob.perform_async(1, 2, 3)
|
16
|
+
#
|
17
|
+
# In your tests:
|
18
|
+
#
|
19
|
+
# LogJob.jobs => [{ "args" => [1, 2, 3]]
|
20
|
+
|
21
|
+
module SuckerPunch
|
22
|
+
module Job
|
23
|
+
def self.jobs
|
24
|
+
SuckerPunch::Queue.find_or_create(self.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.clear_all
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Queue
|
33
|
+
def self.find_or_create(name, _number_workers = 2, _num_jobs_max = nil)
|
34
|
+
QUEUES.fetch_or_store(name) do
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def kill
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -17,7 +17,7 @@ require 'sucker_punch'
|
|
17
17
|
#
|
18
18
|
# Include inline testing lib:
|
19
19
|
#
|
20
|
-
# require 'sucker_punch/testing/inline
|
20
|
+
# require 'sucker_punch/testing/inline'
|
21
21
|
#
|
22
22
|
# LogJob.perform_async(1, 2, 3) is now synchronous
|
23
23
|
# LogJob.perform_in(1, 2, 3) is now synchronous
|
@@ -25,12 +25,12 @@ require 'sucker_punch'
|
|
25
25
|
module SuckerPunch
|
26
26
|
module Job
|
27
27
|
module ClassMethods
|
28
|
-
def perform_async(*args)
|
29
|
-
self.new.perform(*args)
|
28
|
+
def perform_async(*args, **kwargs)
|
29
|
+
self.new.perform(*args, **kwargs)
|
30
30
|
end
|
31
31
|
|
32
|
-
def perform_in(_, *args)
|
33
|
-
self.new.perform(*args)
|
32
|
+
def perform_in(_, *args, **kwargs)
|
33
|
+
self.new.perform(*args, **kwargs)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
data/lib/sucker_punch/version.rb
CHANGED
data/sucker_punch.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Brandon Hilkert"]
|
10
10
|
gem.email = ["brandonhilkert@gmail.com"]
|
11
11
|
gem.description = %q{Asynchronous processing library for Ruby}
|
12
|
-
gem.summary = %q{Sucker Punch is a Ruby asynchronous processing using
|
12
|
+
gem.summary = %q{Sucker Punch is a Ruby asynchronous processing using concurrent-ruby, heavily influenced by Sidekiq and girl_friday.}
|
13
13
|
gem.homepage = "https://github.com/brandonhilkert/sucker_punch"
|
14
14
|
gem.license = "MIT"
|
15
15
|
|
@@ -18,11 +18,17 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.post_install_message = "Sucker Punch v2.0 introduces backwards-incompatible changes.\nPlease see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#
|
21
|
+
gem.post_install_message = "Sucker Punch v2.0 introduces backwards-incompatible changes.\nPlease see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#200 for details."
|
22
22
|
|
23
23
|
gem.add_development_dependency "rake", "~> 10.0"
|
24
24
|
gem.add_development_dependency "minitest"
|
25
25
|
gem.add_development_dependency "pry"
|
26
26
|
|
27
|
-
gem.add_dependency "concurrent-ruby", "~> 1.0
|
27
|
+
gem.add_dependency "concurrent-ruby", "~> 1.0"
|
28
|
+
|
29
|
+
if gem.respond_to?(:metadata)
|
30
|
+
gem.metadata['changelog_uri'] = 'https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md'
|
31
|
+
gem.metadata['source_code_uri'] = 'https://github.com/brandonhilkert/sucker_punch'
|
32
|
+
gem.metadata['bug_tracker_uri'] = 'https://github.com/brandonhilkert/sucker_punch/issues'
|
33
|
+
end
|
28
34
|
end
|
@@ -55,6 +55,11 @@ module SuckerPunch
|
|
55
55
|
FakeLogJob.workers(2)
|
56
56
|
end
|
57
57
|
|
58
|
+
def test_can_set_max_jobs
|
59
|
+
FakeLogJob.max_jobs(10)
|
60
|
+
assert_equal 10, FakeLogJob.num_jobs_max
|
61
|
+
end
|
62
|
+
|
58
63
|
def test_logger_is_accessible_from_instance
|
59
64
|
SuckerPunch.logger = SuckerPunch.default_logger
|
60
65
|
assert_equal SuckerPunch.logger, FakeLogJob.new.logger
|
@@ -177,4 +182,3 @@ module SuckerPunch
|
|
177
182
|
end
|
178
183
|
end
|
179
184
|
end
|
180
|
-
|
@@ -29,6 +29,11 @@ module SuckerPunch
|
|
29
29
|
assert_equal 4, queue.min_length
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_queue_max_queue_can_be_set
|
33
|
+
queue = SuckerPunch::Queue.find_or_create(@queue, 4, 10)
|
34
|
+
assert_equal(10, queue.max_queue)
|
35
|
+
end
|
36
|
+
|
32
37
|
def test_same_queue_is_returned_on_subsequent_queries
|
33
38
|
queue = SuckerPunch::Queue.find_or_create(@queue)
|
34
39
|
assert_equal queue, SuckerPunch::Queue.find_or_create(@queue)
|
@@ -82,33 +87,29 @@ module SuckerPunch
|
|
82
87
|
assert_equal true, queue.running?
|
83
88
|
end
|
84
89
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
queue = SuckerPunch::Queue.new "fake", fake_pool
|
89
|
-
queue.post(1, 2) { |args| arr.push args }
|
90
|
-
assert_equal [1, 2], arr.first
|
90
|
+
def test_idle_considers_queue_workers_and_length
|
91
|
+
queue = SuckerPunch::Queue.find_or_create(FakeNilJob.to_s)
|
92
|
+
assert_equal true, queue.idle?
|
91
93
|
end
|
92
94
|
|
93
|
-
def
|
95
|
+
def test_jobs_can_be_posted_to_pool
|
94
96
|
arr = []
|
95
97
|
fake_pool = FakePool.new
|
96
|
-
queue
|
97
|
-
queue.kill
|
98
|
+
queue = SuckerPunch::Queue.new "fake", fake_pool
|
98
99
|
queue.post(1, 2) { |args| arr.push args }
|
99
|
-
|
100
|
+
assert_equal [1, 2], arr.first
|
100
101
|
end
|
101
102
|
|
102
103
|
def test_kill_sends_kill_to_pool
|
103
104
|
fake_pool = FakePool.new
|
104
|
-
queue
|
105
|
+
queue = SuckerPunch::Queue.new "fake", fake_pool
|
105
106
|
queue.kill
|
106
107
|
assert_equal :kill, fake_pool.signals.first
|
107
108
|
end
|
108
109
|
|
109
110
|
def test_shutdown_sends_shutdown_to_pool
|
110
111
|
fake_pool = FakePool.new
|
111
|
-
queue
|
112
|
+
queue = SuckerPunch::Queue.new "fake", fake_pool
|
112
113
|
queue.shutdown
|
113
114
|
assert_equal :shutdown, fake_pool.signals.first
|
114
115
|
end
|
@@ -135,9 +136,9 @@ module SuckerPunch
|
|
135
136
|
@signals = []
|
136
137
|
end
|
137
138
|
|
138
|
-
def post(*args, &block)
|
139
|
+
def post(*args, **kwargs, &block)
|
139
140
|
if block_given?
|
140
|
-
block.call(args)
|
141
|
+
block.call(args, **kwargs)
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
data/test/sucker_punch_test.rb
CHANGED
@@ -41,7 +41,7 @@ class SuckerPunchTest < Minitest::Test
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_exception_handler_can_be_set
|
44
|
-
SuckerPunch.exception_handler = -> (
|
44
|
+
SuckerPunch.exception_handler = -> (_ex, _, _) { raise "bad stuff" }
|
45
45
|
assert_raises(::RuntimeError) { SuckerPunch.exception_handler.call(StandardError.new("bad"), nil, nil) }
|
46
46
|
end
|
47
47
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sucker_punch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Hilkert
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0
|
61
|
+
version: '1.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.0
|
68
|
+
version: '1.0'
|
69
69
|
description: Asynchronous processing library for Ruby
|
70
70
|
email:
|
71
71
|
- brandonhilkert@gmail.com
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/sucker_punch/job.rb
|
90
90
|
- lib/sucker_punch/queue.rb
|
91
91
|
- lib/sucker_punch/railtie.rb
|
92
|
+
- lib/sucker_punch/testing.rb
|
92
93
|
- lib/sucker_punch/testing/inline.rb
|
93
94
|
- lib/sucker_punch/version.rb
|
94
95
|
- sucker_punch.gemspec
|
@@ -101,10 +102,13 @@ files:
|
|
101
102
|
homepage: https://github.com/brandonhilkert/sucker_punch
|
102
103
|
licenses:
|
103
104
|
- MIT
|
104
|
-
metadata:
|
105
|
+
metadata:
|
106
|
+
changelog_uri: https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md
|
107
|
+
source_code_uri: https://github.com/brandonhilkert/sucker_punch
|
108
|
+
bug_tracker_uri: https://github.com/brandonhilkert/sucker_punch/issues
|
105
109
|
post_install_message: |-
|
106
110
|
Sucker Punch v2.0 introduces backwards-incompatible changes.
|
107
|
-
Please see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#
|
111
|
+
Please see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#200 for details.
|
108
112
|
rdoc_options: []
|
109
113
|
require_paths:
|
110
114
|
- lib
|
@@ -119,12 +123,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
123
|
- !ruby/object:Gem::Version
|
120
124
|
version: '0'
|
121
125
|
requirements: []
|
122
|
-
|
123
|
-
|
124
|
-
signing_key:
|
126
|
+
rubygems_version: 3.1.2
|
127
|
+
signing_key:
|
125
128
|
specification_version: 4
|
126
|
-
summary: Sucker Punch is a Ruby asynchronous processing using
|
127
|
-
by Sidekiq and girl_friday.
|
129
|
+
summary: Sucker Punch is a Ruby asynchronous processing using concurrent-ruby, heavily
|
130
|
+
influenced by Sidekiq and girl_friday.
|
128
131
|
test_files:
|
129
132
|
- test/sucker_punch/async_syntax_test.rb
|
130
133
|
- test/sucker_punch/counter_test.rb
|