sucker_punch 1.6.0 → 2.0.0.beta1
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/.travis.yml +15 -3
- data/CHANGES.md +30 -0
- data/README.md +99 -96
- data/Rakefile +9 -6
- data/bin/load +23 -0
- data/bin/shutdown +20 -0
- data/lib/sucker_punch/async_syntax.rb +18 -0
- data/lib/sucker_punch/core_ext.rb +50 -8
- data/lib/sucker_punch/counter.rb +72 -0
- data/lib/sucker_punch/job.rb +53 -10
- data/lib/sucker_punch/queue.rb +159 -34
- data/lib/sucker_punch/testing/inline.rb +33 -7
- data/lib/sucker_punch/version.rb +1 -1
- data/lib/sucker_punch.rb +46 -9
- data/sucker_punch.gemspec +5 -3
- data/test/sucker_punch/async_syntax_test.rb +33 -0
- data/test/sucker_punch/counter_test.rb +83 -0
- data/test/sucker_punch/job_test.rb +157 -0
- data/test/sucker_punch/queue_test.rb +99 -0
- data/test/sucker_punch_test.rb +52 -0
- data/test/test_helper.rb +8 -0
- metadata +36 -29
- data/spec/spec_helper.rb +0 -9
- data/spec/sucker_punch/core_ext_spec.rb +0 -13
- data/spec/sucker_punch/job_spec.rb +0 -42
- data/spec/sucker_punch/queue_spec.rb +0 -69
- data/spec/sucker_punch/testing/inline_spec.rb +0 -18
- data/spec/sucker_punch_spec.rb +0 -14
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module SuckerPunch
|
4
|
+
class QueueTest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@queue = "fake"
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
SuckerPunch::Queue.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_queue_is_created_if_it_doesnt_exist
|
14
|
+
SuckerPunch::Queue::QUEUES.clear
|
15
|
+
assert SuckerPunch::Queue::QUEUES.empty?
|
16
|
+
queue = SuckerPunch::Queue.find_or_create(@queue)
|
17
|
+
assert queue.send(:pool).is_a?(Concurrent::ThreadPoolExecutor)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_queue_is_created_with_2_workers
|
21
|
+
queue = SuckerPunch::Queue.find_or_create(@queue)
|
22
|
+
assert_equal 2, queue.max_length
|
23
|
+
assert_equal 2, queue.min_length
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_queue_num_workers_can_be_set
|
27
|
+
queue = SuckerPunch::Queue.find_or_create(@queue, 4)
|
28
|
+
assert_equal 4, queue.max_length
|
29
|
+
assert_equal 4, queue.min_length
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_same_queue_is_returned_on_subsequent_queries
|
33
|
+
SuckerPunch::Queue::QUEUES.clear
|
34
|
+
queue = SuckerPunch::Queue.find_or_create(@queue)
|
35
|
+
assert_equal queue, SuckerPunch::Queue.find_or_create(@queue)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_all_returns_all_instances_of_a_queue
|
39
|
+
queue1 = SuckerPunch::Queue.find_or_create("fake")
|
40
|
+
queue2 = SuckerPunch::Queue.find_or_create("other_fake")
|
41
|
+
assert SuckerPunch::Queue.all.is_a?(Array)
|
42
|
+
assert SuckerPunch::Queue.all.first.is_a?(SuckerPunch::Queue)
|
43
|
+
assert SuckerPunch::Queue.all.include?(queue1)
|
44
|
+
assert SuckerPunch::Queue.all.include?(queue2)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_clear_removes_queues_and_stats
|
48
|
+
SuckerPunch::Queue.find_or_create(@queue)
|
49
|
+
SuckerPunch::Counter::Busy.new(@queue).increment
|
50
|
+
SuckerPunch::Counter::Processed.new(@queue).increment
|
51
|
+
SuckerPunch::Counter::Failed.new(@queue).increment
|
52
|
+
|
53
|
+
SuckerPunch::Queue.clear
|
54
|
+
|
55
|
+
assert SuckerPunch::Counter::Busy.new(@queue).value == 0
|
56
|
+
assert SuckerPunch::Counter::Processed.new(@queue).value == 0
|
57
|
+
assert SuckerPunch::Counter::Failed.new(@queue).value == 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_returns_queue_stats
|
61
|
+
latch = Concurrent::CountDownLatch.new
|
62
|
+
|
63
|
+
# run a job to setup workers
|
64
|
+
2.times { FakeNilJob.perform_async }
|
65
|
+
|
66
|
+
queue = SuckerPunch::Queue.find_or_create(FakeNilJob.to_s)
|
67
|
+
queue.post { latch.count_down }
|
68
|
+
latch.wait(0.1)
|
69
|
+
|
70
|
+
all_stats = SuckerPunch::Queue.stats
|
71
|
+
stats = all_stats[FakeNilJob.to_s]
|
72
|
+
assert stats["workers"]["total"] > 0
|
73
|
+
assert stats["workers"]["busy"] == 0
|
74
|
+
assert stats["workers"]["idle"] > 0
|
75
|
+
assert stats["jobs"]["processed"] > 0
|
76
|
+
assert stats["jobs"]["failed"] == 0
|
77
|
+
assert stats["jobs"]["enqueued"] == 0
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_queue_name_is_accessible
|
81
|
+
queue = SuckerPunch::Queue.find_or_create(FakeNilJob.to_s)
|
82
|
+
assert_equal "SuckerPunch::QueueTest::FakeNilJob", queue.name
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_default_running_state_is_true
|
86
|
+
queue = SuckerPunch::Queue.find_or_create(FakeNilJob.to_s)
|
87
|
+
assert_equal true, queue.running?
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
class FakeNilJob
|
93
|
+
include SuckerPunch::Job
|
94
|
+
def perform
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SuckerPunchTest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
SuckerPunch::Queue.clear
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
SuckerPunch::Queue.clear
|
10
|
+
SuckerPunch.logger = nil
|
11
|
+
SuckerPunch.exception_handler = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_that_it_has_a_version_number
|
15
|
+
refute_nil ::SuckerPunch::VERSION
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_logger_defaults_to_stdout
|
19
|
+
SuckerPunch.logger = SuckerPunch.default_logger
|
20
|
+
assert SuckerPunch.logger.is_a?(Logger)
|
21
|
+
assert_equal Logger::INFO, SuckerPunch.logger.level
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_can_reset_logger
|
25
|
+
SuckerPunch.logger = nil
|
26
|
+
assert SuckerPunch.logger.is_a?(Logger)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_logger_can_be_set
|
30
|
+
logger = Logger.new(nil)
|
31
|
+
SuckerPunch.logger = logger
|
32
|
+
assert_equal logger, SuckerPunch.logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_default_exception_handler_is_logger
|
36
|
+
@mock = Minitest::Mock.new
|
37
|
+
SuckerPunch.logger = @mock
|
38
|
+
@mock.expect(:error, nil, ["Sucker Punch job error for class: '' args: []\nStandardError fake\n"])
|
39
|
+
SuckerPunch.exception_handler.call(StandardError.new("fake"), '', [])
|
40
|
+
assert @mock.verify
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_exception_handler_can_be_set
|
44
|
+
SuckerPunch.exception_handler = -> (ex, _, _) { raise "bad stuff" }
|
45
|
+
assert_raises(::RuntimeError) { SuckerPunch.exception_handler.call(StandardError.new("bad"), nil, nil) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_shutdown_timeout_can_be_set
|
49
|
+
SuckerPunch.shutdown_timeout = 15
|
50
|
+
assert_equal 15, SuckerPunch.shutdown_timeout
|
51
|
+
end
|
52
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sucker_punch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Hilkert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '10.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '10.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -53,23 +53,25 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: concurrent-ruby
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 1.0.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: 0.
|
68
|
+
version: 1.0.0
|
69
69
|
description: Asynchronous processing library for Ruby
|
70
70
|
email:
|
71
71
|
- brandonhilkert@gmail.com
|
72
|
-
executables:
|
72
|
+
executables:
|
73
|
+
- load
|
74
|
+
- shutdown
|
73
75
|
extensions: []
|
74
76
|
extra_rdoc_files: []
|
75
77
|
files:
|
@@ -80,27 +82,33 @@ files:
|
|
80
82
|
- LICENSE.txt
|
81
83
|
- README.md
|
82
84
|
- Rakefile
|
85
|
+
- bin/load
|
86
|
+
- bin/shutdown
|
83
87
|
- lib/generators/sucker_punch/job_generator.rb
|
84
88
|
- lib/generators/sucker_punch/templates/job.rb
|
85
89
|
- lib/sucker_punch.rb
|
90
|
+
- lib/sucker_punch/async_syntax.rb
|
86
91
|
- lib/sucker_punch/core_ext.rb
|
92
|
+
- lib/sucker_punch/counter.rb
|
87
93
|
- lib/sucker_punch/job.rb
|
88
94
|
- lib/sucker_punch/queue.rb
|
89
95
|
- lib/sucker_punch/railtie.rb
|
90
96
|
- lib/sucker_punch/testing/inline.rb
|
91
97
|
- lib/sucker_punch/version.rb
|
92
|
-
- spec/spec_helper.rb
|
93
|
-
- spec/sucker_punch/core_ext_spec.rb
|
94
|
-
- spec/sucker_punch/job_spec.rb
|
95
|
-
- spec/sucker_punch/queue_spec.rb
|
96
|
-
- spec/sucker_punch/testing/inline_spec.rb
|
97
|
-
- spec/sucker_punch_spec.rb
|
98
98
|
- sucker_punch.gemspec
|
99
|
+
- test/sucker_punch/async_syntax_test.rb
|
100
|
+
- test/sucker_punch/counter_test.rb
|
101
|
+
- test/sucker_punch/job_test.rb
|
102
|
+
- test/sucker_punch/queue_test.rb
|
103
|
+
- test/sucker_punch_test.rb
|
104
|
+
- test/test_helper.rb
|
99
105
|
homepage: https://github.com/brandonhilkert/sucker_punch
|
100
106
|
licenses:
|
101
107
|
- MIT
|
102
108
|
metadata: {}
|
103
|
-
post_install_message:
|
109
|
+
post_install_message: Sucker Punch Version 2.0 introduces backwards-incompatible changes.
|
110
|
+
Please see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#20
|
111
|
+
for details.
|
104
112
|
rdoc_options: []
|
105
113
|
require_paths:
|
106
114
|
- lib
|
@@ -111,21 +119,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
119
|
version: '0'
|
112
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
121
|
requirements:
|
114
|
-
- - "
|
122
|
+
- - ">"
|
115
123
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
124
|
+
version: 1.3.1
|
117
125
|
requirements: []
|
118
126
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.
|
127
|
+
rubygems_version: 2.5.1
|
120
128
|
signing_key:
|
121
129
|
specification_version: 4
|
122
130
|
summary: Sucker Punch is a Ruby asynchronous processing using Celluloid, heavily influenced
|
123
131
|
by Sidekiq and girl_friday.
|
124
132
|
test_files:
|
125
|
-
-
|
126
|
-
-
|
127
|
-
-
|
128
|
-
-
|
129
|
-
-
|
130
|
-
-
|
131
|
-
has_rdoc:
|
133
|
+
- test/sucker_punch/async_syntax_test.rb
|
134
|
+
- test/sucker_punch/counter_test.rb
|
135
|
+
- test/sucker_punch/job_test.rb
|
136
|
+
- test/sucker_punch/queue_test.rb
|
137
|
+
- test/sucker_punch_test.rb
|
138
|
+
- test/test_helper.rb
|
data/spec/spec_helper.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SuckerPunch::Job do
|
4
|
-
before :each do
|
5
|
-
class ::FakeJob
|
6
|
-
include SuckerPunch::Job
|
7
|
-
workers 4
|
8
|
-
|
9
|
-
def perform(name)
|
10
|
-
"response #{name}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
after :each do
|
16
|
-
Celluloid::Actor.clear_registry
|
17
|
-
end
|
18
|
-
|
19
|
-
it "includes Celluloid into requesting class when included" do
|
20
|
-
expect(FakeJob).to respond_to(:pool)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "sets the pool size to 4" do
|
24
|
-
pool = FakeJob.new
|
25
|
-
expect(pool.size).to eq(4)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "returns the same pool on each instantiation" do
|
29
|
-
pool = FakeJob.new
|
30
|
-
pool2 = FakeJob.new
|
31
|
-
expect(pool.thread).to eq(pool2.thread)
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "when pool hasn't been created" do
|
35
|
-
it "registers queue" do
|
36
|
-
queue = double("queue")
|
37
|
-
allow(SuckerPunch::Queue).to receive(:new).and_return(queue)
|
38
|
-
expect(queue).to receive(:register){ 4 }
|
39
|
-
pool = FakeJob.new
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SuckerPunch::Queue 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
|
-
after :each do
|
15
|
-
Celluloid::Actor.clear_registry
|
16
|
-
end
|
17
|
-
|
18
|
-
describe ".find" do
|
19
|
-
it "returns the Celluloid Actor from the registry" do
|
20
|
-
SuckerPunch::Queue.new(FakeJob).register
|
21
|
-
queue = SuckerPunch::Queue.find(FakeJob)
|
22
|
-
expect(queue.class).to eq Celluloid::Supervision::Container::Pool
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "#register" do
|
27
|
-
let(:job) { FakeJob }
|
28
|
-
let(:queue) { SuckerPunch::Queue.new(job) }
|
29
|
-
|
30
|
-
it "initializes and registers the pool with Celluloid" do
|
31
|
-
expected_pool_name = "#{SuckerPunch::Queue::PREFIX}_fake_job".to_sym
|
32
|
-
|
33
|
-
pool = queue.register
|
34
|
-
|
35
|
-
expect(Celluloid::Actor[expected_pool_name]).to eq(pool)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "registers the pool with Celluloid and 3 workers" do
|
39
|
-
expected_pool_name = "#{SuckerPunch::Queue::PREFIX}_fake_job"
|
40
|
-
|
41
|
-
queue.register(3)
|
42
|
-
|
43
|
-
expect(Celluloid::Actor[expected_pool_name].size).to eq(3)
|
44
|
-
end
|
45
|
-
|
46
|
-
context "when too many workers are specified" do
|
47
|
-
it "raises a MaxWorkersExceeded exception" do
|
48
|
-
expect{ queue.register(201) }.to raise_error(SuckerPunch::Queue::MaxWorkersExceeded)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "when too few workers are specified" do
|
53
|
-
it "raises a NotEnoughWorkers exception" do
|
54
|
-
expect{ queue.register(0) }.to raise_error(SuckerPunch::Queue::NotEnoughWorkers)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "#registered?" do
|
60
|
-
it "returns true if queue has already been registered" do
|
61
|
-
queue = SuckerPunch::Queue.new(FakeJob)
|
62
|
-
|
63
|
-
expect{
|
64
|
-
queue.register
|
65
|
-
}.to change{ queue.registered? }.from(false).to(true)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative '../../../lib/sucker_punch/testing/inline'
|
3
|
-
|
4
|
-
describe "SuckerPunch Inline Testing" do
|
5
|
-
before :each do
|
6
|
-
class PatchedJob
|
7
|
-
def perform
|
8
|
-
"do stuff"
|
9
|
-
end
|
10
|
-
include SuckerPunch::Job
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
it "processes jobs inline" do
|
15
|
-
job = PatchedJob.new.async.perform
|
16
|
-
expect(job).to eq "do stuff"
|
17
|
-
end
|
18
|
-
end
|
data/spec/sucker_punch_spec.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SuckerPunch do
|
4
|
-
describe 'logger' do
|
5
|
-
it "delegates get to Celluloid's logger" do
|
6
|
-
expect(SuckerPunch.logger).to eq Celluloid.logger
|
7
|
-
end
|
8
|
-
|
9
|
-
it "delegates set to Celluloid's logger" do
|
10
|
-
expect(Celluloid).to receive(:logger=)
|
11
|
-
SuckerPunch.logger = nil
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|