sucker_punch 0.5.1 → 1.0.0.beta
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 +4 -4
- data/CHANGES.md +7 -0
- data/README.md +36 -139
- data/lib/sucker_punch.rb +3 -18
- data/lib/sucker_punch/core_ext.rb +9 -0
- data/lib/sucker_punch/job.rb +21 -0
- data/lib/sucker_punch/queue.rb +38 -20
- data/lib/sucker_punch/queues.rb +14 -0
- data/lib/sucker_punch/testing/inline.rb +0 -1
- data/lib/sucker_punch/version.rb +1 -1
- data/spec/spec_helper.rb +7 -0
- data/spec/sucker_punch/core_ext_spec.rb +13 -0
- data/spec/sucker_punch/job_spec.rb +34 -0
- data/spec/sucker_punch/queue_spec.rb +34 -34
- data/spec/sucker_punch/queues_spec.rb +17 -0
- data/spec/sucker_punch/testing/inline_spec.rb +9 -11
- data/spec/sucker_punch_spec.rb +0 -38
- data/sucker_punch.gemspec +1 -0
- metadata +27 -11
- data/lib/sucker_punch/exceptions.rb +0 -5
- data/lib/sucker_punch/testing.rb +0 -44
- data/lib/sucker_punch/worker.rb +0 -7
- data/spec/sucker_punch/testing_spec.rb +0 -88
- data/spec/sucker_punch/worker_spec.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d30899558c37fb7f4f048e63520446ab0713746e
|
4
|
+
data.tar.gz: d1d3aa2d0e641b78b30c17fc49f48ddab368cbb9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2568a1953bedf82b39675ce6a4d55ec0d60266aaf5c6e5c7203b0ccd6cab8d4bdd9a5e393a4badd9e3bc6a4e75e7e320c8657ce548828c617da2b2b755d1e292
|
7
|
+
data.tar.gz: 4b9355da76ac828677c9081330e64c48b9c85618f466c4b3149afc47233e3b163b2b9a7871dbb9b781efe3abd3eb8d00e67d83d7bf3161997dfebffc0c620391
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](https://travis-ci.org/brandonhilkert/sucker_punch)
|
4
4
|
[](https://codeclimate.com/github/brandonhilkert/sucker_punch)
|
5
5
|
|
6
|
-
Sucker Punch is a single-process Ruby asynchronous processing library. It's [girl_friday](https://github.com/mperham/girl_friday)
|
6
|
+
Sucker Punch is a single-process Ruby asynchronous processing library. It's [girl_friday](https://github.com/mperham/girl_friday) and DSL sugar on top of [Celluloid](https://github.com/celluloid/celluloid/). With Celluloid's actor pattern, we can do asynchronous processing within a single process. This reduces costs of hosting on a service like Heroku along with the memory footprint of having to maintain additional jobs if hosting on a dedicated server. All queues can run within a single Rails/Sinatra process.
|
7
7
|
|
8
8
|
Sucker Punch is perfect for asynchronous processes like emailing, data crunching, or social platform manipulation. No reason to hold up a user when you can do these things in the background within the same process as your web application...
|
9
9
|
|
@@ -21,25 +21,19 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
$ gem install sucker_punch
|
23
23
|
|
24
|
-
##
|
24
|
+
## Usage
|
25
25
|
|
26
|
+
Each job should be a separate Ruby class and should:
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
* Add `include SuckerPunch::Job`
|
29
|
+
* Define the instance method `perform`, which should be the code the job will run when enqueued
|
29
30
|
|
30
|
-
SuckerPunch.config do
|
31
|
-
queue name: :log_queue, worker: LogWorker, workers: 10
|
32
|
-
queue name: :awesome_queue, worker: AwesomeWorker, workers: 2
|
33
|
-
end
|
34
|
-
```
|
35
|
-
|
36
|
-
## Usage
|
37
31
|
|
38
32
|
```Ruby
|
39
|
-
# app/
|
33
|
+
# app/jobs/log_job.rb
|
40
34
|
|
41
|
-
class
|
42
|
-
include SuckerPunch::
|
35
|
+
class LogJob
|
36
|
+
include SuckerPunch::Job
|
43
37
|
|
44
38
|
def perform(event)
|
45
39
|
Log.new(event).track
|
@@ -47,16 +41,25 @@ class LogWorker
|
|
47
41
|
end
|
48
42
|
```
|
49
43
|
|
50
|
-
|
44
|
+
Synchronous:
|
45
|
+
|
46
|
+
```Ruby
|
47
|
+
LogJob.new.perform("login")
|
48
|
+
```
|
49
|
+
|
50
|
+
Asynchronous:
|
51
51
|
|
52
|
-
|
52
|
+
```Ruby
|
53
|
+
LogJob.new.async.perform("login") # => nil
|
54
|
+
```
|
53
55
|
|
56
|
+
Jobs interacting with `ActiveRecord` should take special precaution not to exhaust connections in the pool. This can be done with `ActiveRecord::Base.connection_pool.with_connection`, which ensures the connection is returned back to the pool when completed.
|
54
57
|
|
55
58
|
```Ruby
|
56
|
-
# app/
|
59
|
+
# app/jobs/awesome_job.rb
|
57
60
|
|
58
|
-
class
|
59
|
-
include SuckerPunch::
|
61
|
+
class AwesomeJob
|
62
|
+
include SuckerPunch::Job
|
60
63
|
|
61
64
|
def perform(user_id)
|
62
65
|
ActiveRecord::Base.connection_pool.with_connection do
|
@@ -70,47 +73,19 @@ end
|
|
70
73
|
We can create a job from within another job:
|
71
74
|
|
72
75
|
```Ruby
|
73
|
-
class
|
74
|
-
include SuckerPunch::
|
76
|
+
class AwesomeJob
|
77
|
+
include SuckerPunch::Job
|
75
78
|
|
76
79
|
def perform(user_id)
|
77
80
|
ActiveRecord::Base.connection_pool.with_connection do
|
78
81
|
user = User.find(user_id)
|
79
82
|
user.update_attributes(is_awesome: true)
|
80
|
-
|
83
|
+
LogJob.new.async.perform("User #{user.id} became awesome!")
|
81
84
|
end
|
82
85
|
end
|
83
86
|
end
|
84
87
|
```
|
85
88
|
|
86
|
-
Queues:
|
87
|
-
|
88
|
-
```Ruby
|
89
|
-
SuckerPunch::Queue[:log_queue] # Just a wrapper for the LogWorker class
|
90
|
-
SuckerPunch::Queue.new(:log_queue)
|
91
|
-
```
|
92
|
-
|
93
|
-
Synchronous:
|
94
|
-
|
95
|
-
```Ruby
|
96
|
-
SuckerPunch::Queue[:log_queue].perform("login")
|
97
|
-
```
|
98
|
-
|
99
|
-
Asynchronous:
|
100
|
-
|
101
|
-
```Ruby
|
102
|
-
SuckerPunch::Queue[:log_queue].async.perform("login") # => nil
|
103
|
-
```
|
104
|
-
|
105
|
-
## Stats
|
106
|
-
|
107
|
-
```Ruby
|
108
|
-
SuckerPunch::Queue[:log_queue].workers # => 10
|
109
|
-
SuckerPunch::Queue[:log_queue].size # => 23 # # of jobs enqueued
|
110
|
-
SuckerPunch::Queue[:log_queue].busy_size # => 7
|
111
|
-
SuckerPunch::Queue[:log_queue].idle_size # => 3
|
112
|
-
```
|
113
|
-
|
114
89
|
## Logger
|
115
90
|
|
116
91
|
```Ruby
|
@@ -118,76 +93,24 @@ SuckerPunch.logger = Logger.new('sucker_punch')
|
|
118
93
|
SuckerPunch.logger # => #<Logger:0x007fa1f28b83f0>
|
119
94
|
```
|
120
95
|
|
121
|
-
If
|
122
|
-
|
123
|
-
## Testing (Only 0.3.1+)
|
124
|
-
|
125
|
-
```Ruby
|
126
|
-
# spec/spec_helper.rb
|
127
|
-
require 'sucker_punch/testing'
|
128
|
-
```
|
129
|
-
|
130
|
-
Requiring this library completely stubs out the internals of Sucker Punch, but will provide the necessary tools to confirm your jobs are being enqueud.
|
131
|
-
|
132
|
-
```Ruby
|
133
|
-
# spec/spec_helper.rb
|
134
|
-
require 'sucker_punch/testing'
|
135
|
-
|
136
|
-
RSpec.configure do |config|
|
137
|
-
config.after do
|
138
|
-
SuckerPunch.reset! # => Resets the queues and jobs in the queues before each test
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# config/initializer/sucker_punch.rb
|
143
|
-
SuckerPunch.config do
|
144
|
-
queue name: :email, worker: EmailWorker, workers: 2
|
145
|
-
end
|
96
|
+
If Sucker Punch is being used within a Rails application, Sucker Punch's logger is set to Rails.logger by default.
|
146
97
|
|
147
|
-
|
148
|
-
class EmailWorker
|
149
|
-
include SuckerPunch::Worker
|
98
|
+
## Testing
|
150
99
|
|
151
|
-
|
152
|
-
user = User.find(user_id)
|
153
|
-
UserMailer.send(email.to_sym, user)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# spec/models/user.rb
|
158
|
-
class User < ActiveRecord::Base
|
159
|
-
def send_welcome_email
|
160
|
-
SuckerPunch::Queue.new(:email).async.perform(:welcome, self.id)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# spec/models/user_spec.rb
|
165
|
-
require 'spec_helper'
|
166
|
-
|
167
|
-
describe User do
|
168
|
-
describe "#send_welcome_email" do
|
169
|
-
user = FactoryGirl.create(:user)
|
170
|
-
expect{
|
171
|
-
user.send_welcome_email
|
172
|
-
}.to change{ SuckerPunch::Queue.new(:email).jobs.size }.by(1)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
```
|
100
|
+
Requiring this library causes your jobs to run everything inline. So a call to the following will actually be SYNCHRONOUS:
|
176
101
|
|
177
102
|
```Ruby
|
178
103
|
# spec/spec_helper.rb
|
179
104
|
require 'sucker_punch/testing/inline'
|
180
105
|
```
|
181
106
|
|
182
|
-
Requiring this library causes your workers to run everything inline. So a call to the following will actually be SYNCHRONOUS.
|
183
|
-
|
184
107
|
```Ruby
|
185
|
-
|
108
|
+
Log.new.async.perform("login") # => Will be synchronous and block until job is finished
|
186
109
|
```
|
187
110
|
|
188
111
|
## Troubleshooting
|
189
112
|
|
190
|
-
If you're running tests in transactions (using DatabaseCleaner or a native solution), Sucker Punch
|
113
|
+
If you're running tests in transactions (using DatabaseCleaner or a native solution), Sucker Punch jobs may have trouble finding database records that were created during test setup because the job class is running in a separate thread and the Transaction operates on a different thread so it clears out the data before the jojob can do its business. The best thing to do is cleanup data created for tests jobs through a truncation strategy by tagging the rspec tests as jobs and then specifying the strategy in `spec_helper` like below:
|
191
114
|
|
192
115
|
```Ruby
|
193
116
|
# spec/spec_helper.rb
|
@@ -196,8 +119,8 @@ RSpec.configure do |config|
|
|
196
119
|
DatabaseCleaner.strategy = :transaction
|
197
120
|
end
|
198
121
|
|
199
|
-
# Clean up all
|
200
|
-
config.before(:each, :
|
122
|
+
# Clean up all jobs specs with truncation
|
123
|
+
config.before(:each, :job => true) do
|
201
124
|
DatabaseCleaner.strategy = :truncation
|
202
125
|
end
|
203
126
|
|
@@ -209,49 +132,23 @@ RSpec.configure do |config|
|
|
209
132
|
DatabaseCleaner.clean
|
210
133
|
end
|
211
134
|
|
212
|
-
# spec/
|
135
|
+
# spec/jobs/email_job_spec.rb
|
213
136
|
require 'spec_helper'
|
214
137
|
|
215
|
-
# Tag the spec as a
|
216
|
-
describe
|
138
|
+
# Tag the spec as a job spec so data is persisted long enough for the test
|
139
|
+
describe EmailJob, job: true do
|
217
140
|
describe "#perform" do
|
218
141
|
let(:user) { FactoryGirl.create(:user) }
|
219
142
|
|
220
143
|
it "delivers an email" do
|
221
144
|
expect {
|
222
|
-
|
145
|
+
EmailJob.new.perform(user.id)
|
223
146
|
}.to change{ ActionMailer::Base.deliveries.size }.by(1)
|
224
147
|
end
|
225
148
|
end
|
226
149
|
end
|
227
150
|
```
|
228
151
|
|
229
|
-
When using Passenger or Unicorn, you should configure the queues within a block that runs after the child process is forked.
|
230
|
-
|
231
|
-
```Ruby
|
232
|
-
# config/unicorn.rb
|
233
|
-
#
|
234
|
-
# The following is only need if in your unicorn config
|
235
|
-
# you set:
|
236
|
-
# preload_app true
|
237
|
-
after_fork do |server, worker|
|
238
|
-
SuckerPunch.config do
|
239
|
-
queue name: :log_queue, worker: LogWorker, workers: 10
|
240
|
-
end
|
241
|
-
end
|
242
|
-
```
|
243
|
-
```Ruby
|
244
|
-
# config/initializers/sucker_punch.rb
|
245
|
-
#
|
246
|
-
if defined?(PhusionPassenger)
|
247
|
-
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
248
|
-
SuckerPunch.config do
|
249
|
-
queue name: :log_queue, worker: LogWorker, workers: 10
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
```
|
254
|
-
|
255
152
|
## Gem Name
|
256
153
|
|
257
154
|
...is awesome. But I can't take credit for it. Thanks to [@jmazzi](https://twitter.com/jmazzi) for his superior naming skills. If you're looking for a name for something, he is the one to go to.
|
data/lib/sucker_punch.rb
CHANGED
@@ -1,26 +1,11 @@
|
|
1
1
|
require 'celluloid'
|
2
|
-
require 'sucker_punch/
|
2
|
+
require 'sucker_punch/core_ext'
|
3
|
+
require 'sucker_punch/job'
|
3
4
|
require 'sucker_punch/queue'
|
4
|
-
require 'sucker_punch/
|
5
|
+
require 'sucker_punch/queues'
|
5
6
|
require 'sucker_punch/version'
|
6
7
|
|
7
8
|
module SuckerPunch
|
8
|
-
def self.config(&block)
|
9
|
-
instance_eval &block
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.queue(options = {})
|
13
|
-
raise MissingQueueName unless options[:name]
|
14
|
-
raise MissingWorkerName unless options[:worker]
|
15
|
-
|
16
|
-
klass = options.fetch(:worker)
|
17
|
-
registry_name = options.fetch(:name)
|
18
|
-
workers = options.fetch(:workers, nil)
|
19
|
-
|
20
|
-
q = Queue.new(registry_name)
|
21
|
-
q.register(klass, workers)
|
22
|
-
end
|
23
|
-
|
24
9
|
def self.logger
|
25
10
|
Celluloid.logger
|
26
11
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SuckerPunch
|
2
|
+
module Job
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:include, ::Celluloid)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
|
7
|
+
base.class_eval do
|
8
|
+
def self.new
|
9
|
+
define_celluloid_pool(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def define_celluloid_pool(klass)
|
16
|
+
SuckerPunch::Queue.new(klass).register
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/sucker_punch/queue.rb
CHANGED
@@ -1,36 +1,54 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
1
3
|
module SuckerPunch
|
2
4
|
class Queue
|
3
|
-
attr_reader :
|
5
|
+
attr_reader :klass
|
6
|
+
attr_accessor :pool
|
7
|
+
|
8
|
+
def self.find(klass)
|
9
|
+
queue = self.new(klass)
|
10
|
+
Celluloid::Actor[queue.name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(klass)
|
14
|
+
@klass = klass
|
15
|
+
@pool = nil
|
16
|
+
@mutex = Mutex.new
|
17
|
+
end
|
4
18
|
|
5
|
-
def
|
6
|
-
@
|
19
|
+
def register
|
20
|
+
@mutex.synchronize {
|
21
|
+
unless registered?
|
22
|
+
initialize_celluloid_pool
|
23
|
+
register_celluloid_pool
|
24
|
+
register_queue_with_master_list
|
25
|
+
end
|
26
|
+
}
|
27
|
+
self.class.find(klass)
|
7
28
|
end
|
8
29
|
|
9
|
-
def
|
10
|
-
|
30
|
+
def registered?
|
31
|
+
SuckerPunch::Queues.all.include?(name)
|
11
32
|
end
|
12
33
|
|
13
|
-
def
|
14
|
-
|
15
|
-
opts[:size] = size if size
|
16
|
-
Celluloid::Actor[name] = klass.send(:pool, opts)
|
34
|
+
def name
|
35
|
+
klass.to_s.underscore.to_sym
|
17
36
|
end
|
18
37
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Celluloid::Actor[name].size
|
38
|
+
private
|
39
|
+
|
40
|
+
def initialize_celluloid_pool
|
41
|
+
self.pool = klass.send(:pool)
|
24
42
|
end
|
25
43
|
|
26
|
-
|
27
|
-
|
28
|
-
def size
|
29
|
-
Celluloid::Actor[name].mailbox.size
|
44
|
+
def register_celluloid_pool
|
45
|
+
Celluloid::Actor[name] = pool
|
30
46
|
end
|
31
47
|
|
32
|
-
def
|
33
|
-
|
48
|
+
def register_queue_with_master_list
|
49
|
+
SuckerPunch::Queues.register(name)
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|
53
|
+
|
54
|
+
|
data/lib/sucker_punch/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SuckerPunch::Job do
|
4
|
+
before :each do
|
5
|
+
class ::FakeJob
|
6
|
+
include SuckerPunch::Job
|
7
|
+
|
8
|
+
def perform(name)
|
9
|
+
"response #{name}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "includes Celluloid into requesting class when included" do
|
15
|
+
FakeJob.should respond_to(:pool)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#perform" do
|
19
|
+
context "when pool hasn't been created" do
|
20
|
+
it "creates pool and registers queue" do
|
21
|
+
expect(Celluloid::Actor[:fake_job]).to eq(nil)
|
22
|
+
expect(SuckerPunch::Queues.all).to eq([])
|
23
|
+
|
24
|
+
# Don't use #async here b/c of a race condition
|
25
|
+
# The expectation will run before the asynchronous
|
26
|
+
# job is executed
|
27
|
+
FakeJob.new.perform("test")
|
28
|
+
|
29
|
+
expect(Celluloid::Actor[:fake_job]).to be
|
30
|
+
expect(SuckerPunch::Queues.all).to eq([:fake_job])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,53 +1,53 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class FakeWorker
|
4
|
-
include Celluloid
|
5
|
-
end
|
6
|
-
|
7
3
|
describe SuckerPunch::Queue do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
before :each do
|
5
|
+
class ::FakeJob
|
6
|
+
include SuckerPunch::Job
|
7
|
+
|
8
|
+
def perform(name)
|
9
|
+
"response #{name}"
|
10
|
+
end
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
|
-
describe "#
|
17
|
-
|
18
|
-
SuckerPunch::Queue.new(
|
14
|
+
describe "#find" do
|
15
|
+
it "returns the Celluloid Actor from the registry" do
|
16
|
+
SuckerPunch::Queue.new(FakeJob).register
|
17
|
+
queue = SuckerPunch::Queue.find(FakeJob)
|
18
|
+
queue.class == Celluloid::PoolManager
|
19
19
|
end
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
describe "#register" do
|
23
|
+
let(:job) { FakeJob }
|
24
|
+
let(:queue) { SuckerPunch::Queue.new(job) }
|
25
|
+
|
26
|
+
it "initializes a celluloid pool" do
|
27
|
+
queue.register
|
28
|
+
expect(queue.pool.class).to eq(Celluloid::PoolManager)
|
25
29
|
end
|
26
30
|
|
27
|
-
it "
|
28
|
-
|
31
|
+
it "registers the pool with Celluloid" do
|
32
|
+
pool = queue.register
|
33
|
+
expect(Celluloid::Actor[:fake_job]).to eq(pool)
|
29
34
|
end
|
30
|
-
end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
SuckerPunch::
|
35
|
-
|
36
|
+
it "registers with master list of queues" do
|
37
|
+
queue.register
|
38
|
+
queues = SuckerPunch::Queues.all
|
39
|
+
expect(queues.size).to be(1)
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
39
|
-
describe "
|
40
|
-
|
43
|
+
describe "#registered?" do
|
44
|
+
it "returns true if queue has already been registered" do
|
45
|
+
queue = SuckerPunch::Queue.new(FakeJob)
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
it "sends messages to Actor" do
|
47
|
-
queue.workers.should == 2
|
48
|
-
queue.idle_size.should == 2
|
49
|
-
queue.busy_size.should == 0
|
50
|
-
queue.size.should == 0
|
47
|
+
expect{
|
48
|
+
queue.register
|
49
|
+
}.to change{ queue.registered? }.from(false).to(true)
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
53
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SuckerPunch::Queues do
|
4
|
+
describe "queue registration and querying" do
|
5
|
+
it "adds a queue to the master queue list" do
|
6
|
+
SuckerPunch::Queues.register(:fake)
|
7
|
+
expect(SuckerPunch::Queues.all).to eq([:fake])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".registered?" do
|
12
|
+
it "returns true if queue has already been registered" do
|
13
|
+
SuckerPunch::Queues.register(:fake)
|
14
|
+
expect{ SuckerPunch::Queues.registered?(:fake) }.to be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,20 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require_relative '../../../lib/sucker_punch/testing/inline'
|
3
3
|
|
4
|
-
class PatchedWorker
|
5
|
-
include SuckerPunch::Worker
|
6
|
-
|
7
|
-
def perform
|
8
|
-
"do stuff"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
SuckerPunch::Queue.new(:patched_queue).register(PatchedWorker, 2)
|
12
|
-
|
13
4
|
describe "SuckerPunch Inline Testing" do
|
14
|
-
|
5
|
+
before :each do
|
6
|
+
class PatchedJob
|
7
|
+
def perform
|
8
|
+
"do stuff"
|
9
|
+
end
|
10
|
+
include SuckerPunch::Job
|
11
|
+
end
|
12
|
+
end
|
15
13
|
|
16
14
|
it "processes jobs inline" do
|
17
|
-
job =
|
15
|
+
job = PatchedJob.new.async.perform
|
18
16
|
expect(job).to eq "do stuff"
|
19
17
|
end
|
20
18
|
end
|
data/spec/sucker_punch_spec.rb
CHANGED
@@ -1,44 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class FakeWorker
|
4
|
-
include Celluloid
|
5
|
-
end
|
6
|
-
|
7
3
|
describe SuckerPunch do
|
8
|
-
context "config" do
|
9
|
-
|
10
|
-
context "properly configured" do
|
11
|
-
it "registers the queue" do
|
12
|
-
SuckerPunch::Queue.any_instance.should_receive(:register).with(FakeWorker, 3)
|
13
|
-
|
14
|
-
SuckerPunch.config do
|
15
|
-
queue name: :crazy_queue, worker: FakeWorker, workers: 3
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "with no queue name" do
|
21
|
-
it "raises an exception" do
|
22
|
-
expect {
|
23
|
-
SuckerPunch.config do
|
24
|
-
queue worker: FakeWorker
|
25
|
-
end
|
26
|
-
}.to raise_error(SuckerPunch::MissingQueueName)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context "with no worker name" do
|
31
|
-
it "raises an exception" do
|
32
|
-
expect {
|
33
|
-
SuckerPunch.config do
|
34
|
-
queue name: :fake
|
35
|
-
end
|
36
|
-
}.to raise_error(SuckerPunch::MissingWorkerName)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
4
|
describe 'logger' do
|
43
5
|
it "delegates get to Celluloid's logger" do
|
44
6
|
SuckerPunch.logger.should == Celluloid.logger
|
data/sucker_punch.gemspec
CHANGED
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: 0.
|
4
|
+
version: 1.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Hilkert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: celluloid
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,18 +81,19 @@ files:
|
|
67
81
|
- README.md
|
68
82
|
- Rakefile
|
69
83
|
- lib/sucker_punch.rb
|
70
|
-
- lib/sucker_punch/
|
84
|
+
- lib/sucker_punch/core_ext.rb
|
85
|
+
- lib/sucker_punch/job.rb
|
71
86
|
- lib/sucker_punch/queue.rb
|
87
|
+
- lib/sucker_punch/queues.rb
|
72
88
|
- lib/sucker_punch/railtie.rb
|
73
|
-
- lib/sucker_punch/testing.rb
|
74
89
|
- lib/sucker_punch/testing/inline.rb
|
75
90
|
- lib/sucker_punch/version.rb
|
76
|
-
- lib/sucker_punch/worker.rb
|
77
91
|
- spec/spec_helper.rb
|
92
|
+
- spec/sucker_punch/core_ext_spec.rb
|
93
|
+
- spec/sucker_punch/job_spec.rb
|
78
94
|
- spec/sucker_punch/queue_spec.rb
|
95
|
+
- spec/sucker_punch/queues_spec.rb
|
79
96
|
- spec/sucker_punch/testing/inline_spec.rb
|
80
|
-
- spec/sucker_punch/testing_spec.rb
|
81
|
-
- spec/sucker_punch/worker_spec.rb
|
82
97
|
- spec/sucker_punch_spec.rb
|
83
98
|
- sucker_punch.gemspec
|
84
99
|
homepage: https://github.com/brandonhilkert/sucker_punch
|
@@ -95,9 +110,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
110
|
version: '0'
|
96
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
112
|
requirements:
|
98
|
-
- - '
|
113
|
+
- - '>'
|
99
114
|
- !ruby/object:Gem::Version
|
100
|
-
version:
|
115
|
+
version: 1.3.1
|
101
116
|
requirements: []
|
102
117
|
rubyforge_project:
|
103
118
|
rubygems_version: 2.0.2
|
@@ -107,8 +122,9 @@ summary: Sucker Punch is a Ruby asynchronous processing using Celluloid, heavily
|
|
107
122
|
by Sidekiq and girl_friday.
|
108
123
|
test_files:
|
109
124
|
- spec/spec_helper.rb
|
125
|
+
- spec/sucker_punch/core_ext_spec.rb
|
126
|
+
- spec/sucker_punch/job_spec.rb
|
110
127
|
- spec/sucker_punch/queue_spec.rb
|
128
|
+
- spec/sucker_punch/queues_spec.rb
|
111
129
|
- spec/sucker_punch/testing/inline_spec.rb
|
112
|
-
- spec/sucker_punch/testing_spec.rb
|
113
|
-
- spec/sucker_punch/worker_spec.rb
|
114
130
|
- spec/sucker_punch_spec.rb
|
data/lib/sucker_punch/testing.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
module SuckerPunch
|
2
|
-
class << self
|
3
|
-
attr_accessor :queues
|
4
|
-
|
5
|
-
def reset!
|
6
|
-
self.queues = {}
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
SuckerPunch.reset!
|
11
|
-
|
12
|
-
class Queue
|
13
|
-
attr_reader :name
|
14
|
-
|
15
|
-
def initialize(name)
|
16
|
-
@name = name
|
17
|
-
SuckerPunch.queues[name] ||= []
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.[](name)
|
21
|
-
new(name)
|
22
|
-
end
|
23
|
-
|
24
|
-
def register(klass, size)
|
25
|
-
nil
|
26
|
-
end
|
27
|
-
|
28
|
-
def workers
|
29
|
-
raise "Not implemented"
|
30
|
-
end
|
31
|
-
|
32
|
-
def jobs
|
33
|
-
SuckerPunch.queues[@name]
|
34
|
-
end
|
35
|
-
|
36
|
-
def async
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def method_missing(name, *args, &block)
|
41
|
-
SuckerPunch.queues[@name] << { method: name, args: Array(args) }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/sucker_punch/worker.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class TestingWorker
|
4
|
-
include Celluloid
|
5
|
-
|
6
|
-
def perform(input)
|
7
|
-
input = "after"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
SuckerPunch.config do
|
12
|
-
queue name: :queue, worker: TestingWorker
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "SuckerPunch Testing" do
|
16
|
-
before :each do
|
17
|
-
require_relative '../../lib/sucker_punch/testing'
|
18
|
-
SuckerPunch.reset!
|
19
|
-
end
|
20
|
-
|
21
|
-
describe ".reset!" do
|
22
|
-
it "resets the queues to be empty" do
|
23
|
-
4.times { SuckerPunch::Queue.new(:queue).async.perform("before") }
|
24
|
-
SuckerPunch.reset!
|
25
|
-
queue = SuckerPunch::Queue.new(:queue)
|
26
|
-
expect(queue.jobs.count).to eq 0
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe Queue do
|
31
|
-
it "returns previous instance when queried again" do
|
32
|
-
queue = SuckerPunch::Queue.new(:queue)
|
33
|
-
queue.async.perform("before")
|
34
|
-
expect(SuckerPunch::Queue.new(:queue).jobs.count).to eq 1
|
35
|
-
end
|
36
|
-
|
37
|
-
describe ".[]" do
|
38
|
-
it "returns the queue instance" do
|
39
|
-
queue = SuckerPunch::Queue.new(:queue)
|
40
|
-
queue.async.perform("before")
|
41
|
-
expect(SuckerPunch::Queue[:queue].jobs.count).to eq 1
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "#register" do
|
46
|
-
it "returns nil" do
|
47
|
-
queue = SuckerPunch::Queue.new(:queue)
|
48
|
-
expect(queue.register(TestingWorker, 3)).to eq nil
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe "#workers" do
|
53
|
-
it "raises an exception if called" do
|
54
|
-
queue = SuckerPunch::Queue.new(:queue)
|
55
|
-
expect{ queue.workers }.to raise_error "Not implemented"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "#jobs" do
|
60
|
-
it "returns an array of the jobs in the queue" do
|
61
|
-
queue = SuckerPunch::Queue.new(:queue)
|
62
|
-
queue.async.perform("before")
|
63
|
-
expect(queue.jobs).to eq [{ method: :perform, args: ["before"] }]
|
64
|
-
end
|
65
|
-
|
66
|
-
it "returns the number of jobs in the queue" do
|
67
|
-
queue = SuckerPunch::Queue.new(:queue)
|
68
|
-
4.times { queue.async.perform("before") }
|
69
|
-
expect(queue.jobs.count).to eq 4
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#async" do
|
74
|
-
it "returns self" do
|
75
|
-
queue = SuckerPunch::Queue.new(:queue)
|
76
|
-
expect(queue.async).to eq queue
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe "enqueueing a job" do
|
81
|
-
it "adds the job to the queue" do
|
82
|
-
queue = SuckerPunch::Queue.new(:queue)
|
83
|
-
queue.async.perform("before")
|
84
|
-
expect(queue.jobs).to eq [{ method: :perform, args: ["before"] }]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class FakeWorker
|
4
|
-
include SuckerPunch::Worker
|
5
|
-
|
6
|
-
def perform
|
7
|
-
puts "do stuff"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
describe SuckerPunch::Worker do
|
12
|
-
it "should include Celluloid into requesting class when included" do
|
13
|
-
FakeWorker.should respond_to(:pool)
|
14
|
-
end
|
15
|
-
end
|