sucker_punch 3.0.0 → 3.0.1
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/.github/workflows/build.yml +37 -0
- data/CHANGES.md +4 -0
- data/lib/sucker_punch/async_syntax.rb +3 -2
- data/lib/sucker_punch/job.rb +10 -11
- data/lib/sucker_punch/queue.rb +3 -2
- data/lib/sucker_punch/testing/inline.rb +6 -4
- data/lib/sucker_punch/version.rb +1 -1
- data/sucker_punch.gemspec +23 -23
- data/test/sucker_punch/async_syntax_test.rb +17 -0
- data/test/sucker_punch/job_test.rb +24 -0
- data/test/sucker_punch/queue_test.rb +10 -3
- metadata +5 -7
- data/.travis.yml +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dfa20a18d1c51b637e21b3b7aa657979a73036964ed8e6542e2b759ebd5adce
|
4
|
+
data.tar.gz: 95aea0e08f0a4a3e9048836c820cd4bde237ac067aa3ad71c2de728fd3ffb8cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2bcf61e16203c7cd4c2eab46d35ae5f1da65e640564ad65beba14b2b9b4579023546432553c0d75b571265a0e60f0ff71a48bd4c3519f809e42628aec298791
|
7
|
+
data.tar.gz: 8b660145d51fa187b63ad897a9342dc8955f1cf045b0b03e1138720f912762b35b624fe292d2c0adb9b3a6bf961ad9cae6e29f4044226b37d0c654e257f2353d
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Build
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ master ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ master ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.1', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '3.0', 'head', 'jruby', 'truffleruby', 'truffleruby-head']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
|
27
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
28
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
29
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
30
|
+
# uses: ruby/setup-ruby@v1
|
31
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
32
|
+
with:
|
33
|
+
ruby-version: ${{ matrix.ruby-version }}
|
34
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
35
|
+
|
36
|
+
- name: Run tests
|
37
|
+
run: bundle exec rake
|
data/CHANGES.md
CHANGED
@@ -10,8 +10,9 @@ module SuckerPunch
|
|
10
10
|
@job = job
|
11
11
|
end
|
12
12
|
|
13
|
-
def perform(*args
|
14
|
-
@job.class.perform_async(*args
|
13
|
+
def perform(*args)
|
14
|
+
@job.class.perform_async(*args)
|
15
15
|
end
|
16
|
+
ruby2_keywords(:perform) if respond_to?(:ruby2_keywords, true)
|
16
17
|
end
|
17
18
|
end
|
data/lib/sucker_punch/job.rb
CHANGED
@@ -32,20 +32,22 @@ module SuckerPunch
|
|
32
32
|
end
|
33
33
|
|
34
34
|
module ClassMethods
|
35
|
-
def perform_async(*args
|
35
|
+
def perform_async(*args)
|
36
36
|
return unless SuckerPunch::RUNNING.true?
|
37
37
|
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
|
38
|
-
queue.post { __run_perform(*args
|
38
|
+
queue.post { __run_perform(*args) }
|
39
39
|
end
|
40
|
+
ruby2_keywords(:perform_async) if respond_to?(:ruby2_keywords, true)
|
40
41
|
|
41
|
-
def perform_in(interval, *args
|
42
|
+
def perform_in(interval, *args)
|
42
43
|
return unless SuckerPunch::RUNNING.true?
|
43
44
|
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
|
44
45
|
job = Concurrent::ScheduledTask.execute(interval.to_f, args: args, executor: queue) do
|
45
|
-
__run_perform(*args
|
46
|
+
__run_perform(*args)
|
46
47
|
end
|
47
48
|
job.pending?
|
48
49
|
end
|
50
|
+
ruby2_keywords(:perform_in) if respond_to?(:ruby2_keywords, true)
|
49
51
|
|
50
52
|
def workers(num)
|
51
53
|
self.num_workers = num
|
@@ -55,23 +57,20 @@ module SuckerPunch
|
|
55
57
|
self.num_jobs_max = num
|
56
58
|
end
|
57
59
|
|
58
|
-
def __run_perform(*args
|
60
|
+
def __run_perform(*args)
|
59
61
|
SuckerPunch::Counter::Busy.new(self.to_s).increment
|
60
62
|
|
61
|
-
result =
|
62
|
-
self.new.perform(*args, **kwargs)
|
63
|
-
else
|
64
|
-
self.new.perform(*args, *(kwargs.any? ? [kwargs] : nil))
|
65
|
-
end
|
63
|
+
result = self.new.perform(*args)
|
66
64
|
|
67
65
|
SuckerPunch::Counter::Processed.new(self.to_s).increment
|
68
66
|
result
|
69
67
|
rescue => ex
|
70
68
|
SuckerPunch::Counter::Failed.new(self.to_s).increment
|
71
|
-
SuckerPunch.exception_handler.call(ex, self, [*args
|
69
|
+
SuckerPunch.exception_handler.call(ex, self, [*args])
|
72
70
|
ensure
|
73
71
|
SuckerPunch::Counter::Busy.new(self.to_s).decrement
|
74
72
|
end
|
73
|
+
ruby2_keywords(:__run_perform) if respond_to?(:ruby2_keywords, true)
|
75
74
|
end
|
76
75
|
end
|
77
76
|
end
|
data/lib/sucker_punch/queue.rb
CHANGED
@@ -165,15 +165,16 @@ module SuckerPunch
|
|
165
165
|
SuckerPunch::Counter::Failed.new(name).value
|
166
166
|
end
|
167
167
|
|
168
|
-
def post(*args,
|
168
|
+
def post(*args, &block)
|
169
169
|
synchronize do
|
170
170
|
if @running
|
171
|
-
@pool.post(*args,
|
171
|
+
@pool.post(*args, &block)
|
172
172
|
else
|
173
173
|
false
|
174
174
|
end
|
175
175
|
end
|
176
176
|
end
|
177
|
+
ruby2_keywords(:post) if respond_to?(:ruby2_keywords, true)
|
177
178
|
|
178
179
|
def kill
|
179
180
|
@pool.kill
|
@@ -25,13 +25,15 @@ 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)
|
29
|
+
self.new.perform(*args)
|
30
30
|
end
|
31
|
+
ruby2_keywords(:perform_async) if respond_to?(:ruby2_keywords, true)
|
31
32
|
|
32
|
-
def perform_in(_, *args
|
33
|
-
self.new.perform(*args
|
33
|
+
def perform_in(_, *args)
|
34
|
+
self.new.perform(*args)
|
34
35
|
end
|
36
|
+
ruby2_keywords(:perform_in) if respond_to?(:ruby2_keywords, true)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
data/lib/sucker_punch/version.rb
CHANGED
data/sucker_punch.gemspec
CHANGED
@@ -3,32 +3,32 @@ lib = File.expand_path('../lib', __FILE__)
|
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'sucker_punch/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sucker_punch"
|
8
|
+
spec.version = SuckerPunch::VERSION
|
9
|
+
spec.authors = ["Brandon Hilkert"]
|
10
|
+
spec.email = ["brandonhilkert@gmail.com"]
|
11
|
+
spec.description = %q{Asynchronous processing library for Ruby}
|
12
|
+
spec.summary = %q{Sucker Punch is a Ruby asynchronous processing using concurrent-ruby, heavily influenced by Sidekiq and girl_friday.}
|
13
|
+
spec.homepage = "https://github.com/brandonhilkert/sucker_punch"
|
14
|
+
spec.license = "MIT"
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
spec.add_development_dependency "pry"
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
28
|
+
|
29
|
+
if spec.respond_to?(:metadata)
|
30
|
+
spec.metadata['changelog_uri'] = 'https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md'
|
31
|
+
spec.metadata['source_code_uri'] = 'https://github.com/brandonhilkert/sucker_punch'
|
32
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/brandonhilkert/sucker_punch/issues'
|
33
33
|
end
|
34
34
|
end
|
@@ -19,6 +19,14 @@ module SuckerPunch
|
|
19
19
|
assert_equal 1, arr.size
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_perform_async_works_with_keywords
|
23
|
+
arr = Concurrent::Array.new
|
24
|
+
latch = Concurrent::CountDownLatch.new
|
25
|
+
FakeKeywordLatchJob.new.async.perform(arr: arr, latch: latch)
|
26
|
+
latch.wait(0.2)
|
27
|
+
assert_equal 1, arr.size
|
28
|
+
end
|
29
|
+
|
22
30
|
private
|
23
31
|
|
24
32
|
class FakeLatchJob
|
@@ -29,5 +37,14 @@ module SuckerPunch
|
|
29
37
|
latch.count_down
|
30
38
|
end
|
31
39
|
end
|
40
|
+
|
41
|
+
class FakeKeywordLatchJob
|
42
|
+
include SuckerPunch::Job
|
43
|
+
|
44
|
+
def perform(arr: Concurrent::Array.new, latch: Concurrent::CountDownLatch.new)
|
45
|
+
arr.push true
|
46
|
+
latch.count_down
|
47
|
+
end
|
48
|
+
end
|
32
49
|
end
|
33
50
|
end
|
@@ -122,6 +122,22 @@ module SuckerPunch
|
|
122
122
|
assert SuckerPunch::Counter::Processed.new(job_class.to_s).value == 1
|
123
123
|
end
|
124
124
|
|
125
|
+
def test_perform_async_handles_keyword_arguments
|
126
|
+
arr = Concurrent::Array.new
|
127
|
+
latch = Concurrent::CountDownLatch.new
|
128
|
+
FakeKeywordLatchJob.perform_async(arr: arr, latch: latch)
|
129
|
+
latch.wait(1)
|
130
|
+
assert_equal 1, arr.size
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_perform_in_handles_keyword_arguments
|
134
|
+
arr = Concurrent::Array.new
|
135
|
+
latch = Concurrent::CountDownLatch.new
|
136
|
+
FakeKeywordLatchJob.perform_in(0.1, arr: arr, latch: latch)
|
137
|
+
latch.wait(1)
|
138
|
+
assert_equal 1, arr.size
|
139
|
+
end
|
140
|
+
|
125
141
|
def test_failed_jobs_is_incremented_when_job_raises
|
126
142
|
job_class = Class.new(FakeErrorJob)
|
127
143
|
jobs = 3
|
@@ -142,6 +158,14 @@ module SuckerPunch
|
|
142
158
|
end
|
143
159
|
end
|
144
160
|
|
161
|
+
class FakeKeywordLatchJob
|
162
|
+
include SuckerPunch::Job
|
163
|
+
def perform(arr: Concurrent::Array.new, latch: Concurrent::CountDownLatch.new)
|
164
|
+
arr.push true
|
165
|
+
latch.count_down
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
145
169
|
class FakeBusyJob
|
146
170
|
include SuckerPunch::Job
|
147
171
|
def perform(latch1, latch2)
|
@@ -70,7 +70,6 @@ module SuckerPunch
|
|
70
70
|
all_stats = SuckerPunch::Queue.stats
|
71
71
|
stats = all_stats[FakeLatchJob.to_s]
|
72
72
|
assert stats["workers"]["total"] > 0
|
73
|
-
assert stats["workers"]["busy"] == 0
|
74
73
|
assert stats["workers"]["idle"] > 0
|
75
74
|
assert stats["jobs"]["processed"] > 0
|
76
75
|
assert stats["jobs"]["failed"] == 0
|
@@ -100,6 +99,14 @@ module SuckerPunch
|
|
100
99
|
assert_equal [1, 2], arr.first
|
101
100
|
end
|
102
101
|
|
102
|
+
def test_jobs_can_be_posted_to_pool_with_keyword_args
|
103
|
+
arr = []
|
104
|
+
fake_pool = FakePool.new
|
105
|
+
queue = SuckerPunch::Queue.new "fake", fake_pool
|
106
|
+
queue.post(a: 1, b: 2) { |args| arr.push args }
|
107
|
+
assert_equal [{a: 1, b: 2}], arr.first
|
108
|
+
end
|
109
|
+
|
103
110
|
def test_kill_sends_kill_to_pool
|
104
111
|
fake_pool = FakePool.new
|
105
112
|
queue = SuckerPunch::Queue.new "fake", fake_pool
|
@@ -136,9 +143,9 @@ module SuckerPunch
|
|
136
143
|
@signals = []
|
137
144
|
end
|
138
145
|
|
139
|
-
def post(*args,
|
146
|
+
def post(*args, &block)
|
140
147
|
if block_given?
|
141
|
-
block.call(args
|
148
|
+
block.call(args)
|
142
149
|
end
|
143
150
|
end
|
144
151
|
|
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: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Hilkert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -73,8 +73,8 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
+
- ".github/workflows/build.yml"
|
76
77
|
- ".gitignore"
|
77
|
-
- ".travis.yml"
|
78
78
|
- CHANGES.md
|
79
79
|
- Gemfile
|
80
80
|
- LICENSE.txt
|
@@ -106,9 +106,7 @@ metadata:
|
|
106
106
|
changelog_uri: https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md
|
107
107
|
source_code_uri: https://github.com/brandonhilkert/sucker_punch
|
108
108
|
bug_tracker_uri: https://github.com/brandonhilkert/sucker_punch/issues
|
109
|
-
post_install_message:
|
110
|
-
Sucker Punch v2.0 introduces backwards-incompatible changes.
|
111
|
-
Please see https://github.com/brandonhilkert/sucker_punch/blob/master/CHANGES.md#200 for details.
|
109
|
+
post_install_message:
|
112
110
|
rdoc_options: []
|
113
111
|
require_paths:
|
114
112
|
- lib
|
@@ -116,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
114
|
requirements:
|
117
115
|
- - ">="
|
118
116
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
117
|
+
version: 2.0.0
|
120
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
119
|
requirements:
|
122
120
|
- - ">="
|