sneakers 2.7.0 → 2.11.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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -6
- data/ChangeLog.md +61 -0
- data/Dockerfile +18 -3
- data/Dockerfile.slim +11 -4
- data/README.md +36 -32
- data/{docker-compose.yaml → docker-compose.yml} +6 -3
- data/lib/sneakers/configuration.rb +0 -1
- data/lib/sneakers/errors.rb +0 -3
- data/lib/sneakers/handlers/maxretry.rb +1 -5
- data/lib/sneakers/handlers/oneshot.rb +0 -4
- data/lib/sneakers/queue.rb +10 -6
- data/lib/sneakers/version.rb +1 -1
- data/lib/sneakers/worker.rb +7 -17
- data/log/.gitkeep +0 -0
- data/sneakers.gemspec +6 -5
- data/spec/sneakers/queue_spec.rb +11 -0
- data/spec/sneakers/runner_spec.rb +2 -2
- data/spec/sneakers/worker_handlers_spec.rb +1 -66
- data/spec/sneakers/worker_spec.rb +13 -62
- data/spec/sneakers/workergroup_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +37 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b012bf95d1ffd483c544a1e58a11775dd1932726
|
4
|
+
data.tar.gz: 5df9669b11a6870968f08483ae1d4bef08becbeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9875ccd366feeb446faaf1c7d9b2aceb8fd3712aaf67e989329eba05ee4c4dc45e0cc5df718a399eeb7302c924b2d131491db75ce9bb824162ae94a734872889
|
7
|
+
data.tar.gz: 7e6e444e6801cc7ddf4bbbfcd197efe6633cda6f004bce71759414aef978669ae1b29136c9135621fffe4b40986546fe237c9b9dd4d6298862416ff5042f97e1
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -4,14 +4,15 @@ services:
|
|
4
4
|
sudo: false
|
5
5
|
cache: bundler
|
6
6
|
language: ruby
|
7
|
+
before_install:
|
8
|
+
- gem install bundler
|
7
9
|
rvm:
|
8
10
|
- ruby-head
|
9
|
-
- "2.
|
10
|
-
- "2.
|
11
|
-
- "2.
|
11
|
+
- "2.5.1"
|
12
|
+
- "2.4.2"
|
13
|
+
- "2.3.5"
|
14
|
+
- "2.2.8"
|
12
15
|
matrix:
|
13
16
|
include:
|
14
|
-
- rvm: 2.
|
17
|
+
- rvm: 2.4.1
|
15
18
|
env: INTEGRATION_LOG=1 INTEGRATION=1
|
16
|
-
|
17
|
-
|
data/ChangeLog.md
CHANGED
@@ -1,5 +1,66 @@
|
|
1
1
|
# Sneakers Change Log
|
2
2
|
|
3
|
+
## Changes Between 2.10.0 and 2.11.0
|
4
|
+
|
5
|
+
This releases includes bug fixes, support for more queue-binding options, better
|
6
|
+
management of the Bunny dependency, and improved documentation. Following is a
|
7
|
+
list of the notable changes:
|
8
|
+
|
9
|
+
### Rescue from ScriptError
|
10
|
+
|
11
|
+
Fixes a bug that would cause Sneakers workers to freeze if an exception
|
12
|
+
descending from `ScriptError`, such as `NotImplementedError`, is raised
|
13
|
+
|
14
|
+
Contributed by @sharshenov
|
15
|
+
|
16
|
+
GitHub Pull Request: [373](https://github.com/jondot/sneakers/pull/373)
|
17
|
+
|
18
|
+
### Loosen Bunny dependency to minor version
|
19
|
+
|
20
|
+
The dependency on Bunny is now pinned to the minor version instead of patch,
|
21
|
+
allowing users to benefit from non-breaking updates to Bunny without having to
|
22
|
+
wait for a Sneakers release.
|
23
|
+
|
24
|
+
Contributed by @olivierlacan
|
25
|
+
|
26
|
+
GitHub Pull Request: [#372](https://github.com/jondot/sneakers/pull/372)
|
27
|
+
|
28
|
+
### Support `:bind_arguments` on bind
|
29
|
+
|
30
|
+
It is now possible to set arguments on a queue when connecting to a headers
|
31
|
+
exchange
|
32
|
+
|
33
|
+
Contributed by @nerikj
|
34
|
+
|
35
|
+
GitHub Pull Request: [#358](https://github.com/jondot/sneakers/pull/358)
|
36
|
+
|
37
|
+
### Other contributions
|
38
|
+
|
39
|
+
This release also contains contributions from @ivan-kolmychek (bumping up Bunny
|
40
|
+
dependency), @michaelklishin (improving code style), and @darren987469 (adding
|
41
|
+
examples to the README)
|
42
|
+
|
43
|
+
## Changes Between 2.8.0 and 2.10.0
|
44
|
+
|
45
|
+
This release contains **minor breaking API changes**.
|
46
|
+
|
47
|
+
### Worker Timeouts are No Longer Enforced
|
48
|
+
|
49
|
+
This is a **breaking change** for `Sneakers::Worker` implementations.
|
50
|
+
|
51
|
+
Timeouts can be disruptive and dangerous depending on what the workers do but not having them can also
|
52
|
+
lead to operational headaches.
|
53
|
+
|
54
|
+
The outcome of [a lengthy discussion](https://github.com/jondot/sneakers/issues/343) on possible
|
55
|
+
alternatives to the timeout mechanisms is that only applications
|
56
|
+
can know where it is safe to enforce a timeout (and how).
|
57
|
+
|
58
|
+
`Sneakers::Worker` implementations are now expected to enforce timeouts
|
59
|
+
in a way that makes sense (and is safe) to them.
|
60
|
+
|
61
|
+
GitHub issues: [#343](https://github.com/jondot/sneakers/issues/343).
|
62
|
+
|
63
|
+
|
3
64
|
## Changes Between 2.6.0 and 2.7.0
|
4
65
|
|
5
66
|
This release requires Ruby 2.2 and has **breaking API changes**
|
data/Dockerfile
CHANGED
@@ -1,13 +1,28 @@
|
|
1
1
|
FROM ruby:2.3-alpine
|
2
2
|
|
3
3
|
RUN apk add --no-cache git
|
4
|
+
|
4
5
|
RUN apk --update add --virtual build_deps \
|
5
|
-
build-base
|
6
|
-
|
6
|
+
build-base \
|
7
|
+
ruby-dev \
|
8
|
+
libc-dev \
|
9
|
+
linux-headers \
|
10
|
+
openssl-dev
|
11
|
+
|
12
|
+
RUN mkdir /myapp
|
7
13
|
|
8
|
-
ADD . /sneakers
|
9
14
|
WORKDIR /sneakers
|
10
15
|
|
16
|
+
COPY lib/sneakers/version.rb /sneakers/lib/sneakers/version.rb
|
17
|
+
|
18
|
+
COPY sneakers.gemspec /sneakers/sneakers.gemspec
|
19
|
+
|
20
|
+
COPY Gemfile /sneakers/Gemfile
|
21
|
+
|
22
|
+
COPY Gemfile.lock /sneakers/Gemfile.lock
|
23
|
+
|
11
24
|
RUN bundle --jobs=4 --retry=3
|
12
25
|
|
26
|
+
COPY . /sneakers
|
27
|
+
|
13
28
|
CMD rake test
|
data/Dockerfile.slim
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
FROM ruby:2.3-alpine
|
2
2
|
|
3
3
|
RUN apk add --no-cache git
|
4
|
+
|
4
5
|
ADD . /sneakers
|
6
|
+
|
5
7
|
WORKDIR /sneakers
|
6
8
|
|
7
9
|
RUN apk --update add --virtual build_deps \
|
8
|
-
build-base
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
build-base \
|
11
|
+
ruby-dev \
|
12
|
+
libc-dev \
|
13
|
+
linux-headers \
|
14
|
+
openssl-dev && \
|
15
|
+
|
16
|
+
bundle --jobs=4 --retry=3 && \
|
17
|
+
|
18
|
+
apk del build_deps
|
12
19
|
|
13
20
|
CMD rake test
|
data/README.md
CHANGED
@@ -4,47 +4,47 @@
|
|
4
4
|
|
5
5
|
```
|
6
6
|
__
|
7
|
-
,--' >
|
8
|
-
`=====
|
7
|
+
,--' >
|
8
|
+
`=====
|
9
9
|
|
10
10
|
```
|
11
11
|
|
12
|
-
|
13
12
|
A high-performance RabbitMQ background processing framework for
|
14
13
|
Ruby.
|
15
14
|
|
16
|
-
|
17
15
|
Sneakers is being used in production for both I/O and CPU intensive workloads, and have achieved the goals of high-performance and 0-maintenance, as designed.
|
18
16
|
|
19
|
-
|
20
|
-
Visit the [wiki](https://github.com/jondot/sneakers/wiki) for
|
21
|
-
documentation and [GitHub releases](https://github.com/jondot/sneakers/releases) for release
|
22
|
-
notes.
|
23
|
-
|
24
|
-
[](https://travis-ci.org/jondot/sneakers)
|
25
|
-
|
26
|
-
|
27
17
|
## Installation
|
28
18
|
|
29
19
|
Add this line to your application's Gemfile:
|
30
20
|
|
31
|
-
```
|
21
|
+
```ruby
|
32
22
|
gem 'sneakers'
|
33
23
|
```
|
34
24
|
|
35
25
|
And then execute:
|
36
26
|
|
37
|
-
```
|
27
|
+
```shell-session
|
38
28
|
$ bundle
|
39
29
|
```
|
40
30
|
|
41
31
|
Or install it yourself as:
|
42
32
|
|
43
|
-
```
|
33
|
+
```shell-session
|
44
34
|
$ gem install sneakers
|
45
35
|
```
|
46
36
|
|
47
|
-
##
|
37
|
+
## Documentation
|
38
|
+
|
39
|
+
A quick start guide is available in the section below.
|
40
|
+
|
41
|
+
Visit the [wiki](https://github.com/jondot/sneakers/wiki) for more detailed
|
42
|
+
documentation and [GitHub releases](https://github.com/jondot/sneakers/releases) for release
|
43
|
+
notes.
|
44
|
+
|
45
|
+
A [change log](./ChangeLog.md) is also available.
|
46
|
+
|
47
|
+
## Quick start
|
48
48
|
|
49
49
|
Set up a Gemfile
|
50
50
|
|
@@ -60,7 +60,6 @@ then create a worker named as `Processor`.
|
|
60
60
|
|
61
61
|
> touch boot.rb
|
62
62
|
|
63
|
-
|
64
63
|
```ruby
|
65
64
|
require 'sneakers'
|
66
65
|
require 'redis'
|
@@ -86,7 +85,6 @@ end
|
|
86
85
|
|
87
86
|
Let's test it out quickly from the command line:
|
88
87
|
|
89
|
-
|
90
88
|
```shell-session
|
91
89
|
$ sneakers work Processor --require boot.rb
|
92
90
|
```
|
@@ -103,6 +101,20 @@ If you go to your RabbitMQ admin now, you'll see a new queue named `logs` was cr
|
|
103
101
|
}
|
104
102
|
```
|
105
103
|
|
104
|
+
Publish a message with the [bunny](https://github.com/ruby-amqp/bunny) gem RabbitMQ client:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
require 'bunny'
|
108
|
+
|
109
|
+
conn = Bunny.new
|
110
|
+
conn.start
|
111
|
+
|
112
|
+
ch = conn.create_channel
|
113
|
+
ch.default_exchange.publish({ type: 'error', message: 'HALP!', error: 'CODE001' }.to_json, routing_key: 'logs')
|
114
|
+
|
115
|
+
conn.close
|
116
|
+
```
|
117
|
+
|
106
118
|
And this is the output you should see at your terminal.
|
107
119
|
|
108
120
|
```
|
@@ -112,7 +124,6 @@ And this is the output you should see at your terminal.
|
|
112
124
|
2013-10-11T19:26:40Z p-4719 t-ovqgyrx8g INFO: log log
|
113
125
|
```
|
114
126
|
|
115
|
-
|
116
127
|
We'll count errors and error types with Redis.
|
117
128
|
|
118
129
|
``` shell-session
|
@@ -120,11 +131,8 @@ $ redis-cli monitor
|
|
120
131
|
1381520329.888581 [0 127.0.0.1:49182] "incr" "processor:CODE001"
|
121
132
|
```
|
122
133
|
|
123
|
-
|
124
134
|
We're basically done with the ceremonies and all is left is to do some real work.
|
125
135
|
|
126
|
-
|
127
|
-
|
128
136
|
### Looking at metrics
|
129
137
|
|
130
138
|
Let's use the `logging_metrics` provider just for the sake of fun of seeing the metrics as they happen.
|
@@ -135,7 +143,7 @@ require 'sneakers'
|
|
135
143
|
require 'redis'
|
136
144
|
require 'json'
|
137
145
|
require 'sneakers/metrics/logging_metrics'
|
138
|
-
Sneakers.configure
|
146
|
+
Sneakers.configure(metrics: Sneakers::Metrics::LoggingMetrics.new)
|
139
147
|
|
140
148
|
# ... rest of code
|
141
149
|
```
|
@@ -150,7 +158,6 @@ Now push a message again and you'll see:
|
|
150
158
|
|
151
159
|
Which increments `started` and `handled.ack`, and times the work unit.
|
152
160
|
|
153
|
-
|
154
161
|
From here, you can continue over to the
|
155
162
|
[Wiki](https://github.com/jondot/sneakers/wiki)
|
156
163
|
|
@@ -161,7 +168,7 @@ If you use Docker, there's some benefits to be had and you can use both
|
|
161
168
|
integration tests or a sample worker without setting up RabbitMQ or the
|
162
169
|
environment needed locally on your development box.
|
163
170
|
|
164
|
-
* To build a container run `docker build
|
171
|
+
* To build a container run `docker build . -t sneakers_sneakers`
|
165
172
|
* To run non-integration tests within a docker container, run `docker run --rm
|
166
173
|
sneakers_sneakers:latest`
|
167
174
|
* To run full integration tests within a docker topology including RabbitMQ,
|
@@ -176,23 +183,20 @@ environment needed locally on your development box.
|
|
176
183
|
It generates a more compact image, while the "regular" `Dockerfile` generates
|
177
184
|
a fatter image - yet faster to iterate when developing
|
178
185
|
|
179
|
-
|
180
186
|
# Compatibility
|
181
187
|
|
182
|
-
* Sneakers
|
183
|
-
* Sneakers 1.
|
188
|
+
* Sneakers 2.7.x and later (using Bunny 2.9) - Ruby 2.2.x
|
189
|
+
* Sneakers 1.1.x and later (using Bunny 2.x) - Ruby 2.x
|
190
|
+
* Sneakers 1.x.x and earlier - Ruby 1.9.x, 2.x
|
184
191
|
|
185
192
|
# Contributing
|
186
193
|
|
187
194
|
Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
|
188
195
|
|
189
|
-
|
190
196
|
### Thanks:
|
191
197
|
|
192
198
|
To all Sneakers [Contributors](https://github.com/jondot/sneakers/graphs/contributors) - you make this happen, thanks!
|
193
199
|
|
194
|
-
|
195
|
-
|
196
200
|
# Copyright
|
197
201
|
|
198
|
-
Copyright (c) 2015 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details.
|
202
|
+
Copyright (c) 2015-2018 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details.
|
@@ -1,17 +1,20 @@
|
|
1
|
-
version: '
|
1
|
+
version: '3'
|
2
|
+
|
2
3
|
services:
|
3
4
|
sneakers:
|
4
5
|
build: .
|
5
6
|
depends_on:
|
6
7
|
- rabbitmq
|
7
8
|
- redis
|
9
|
+
|
8
10
|
rabbitmq:
|
9
|
-
image: rabbitmq:management
|
11
|
+
image: rabbitmq:management-alpine
|
10
12
|
ports:
|
11
13
|
- "5672:5672"
|
12
14
|
- "15672:15672"
|
15
|
+
|
13
16
|
redis:
|
14
|
-
image: redis
|
17
|
+
image: redis:alpine
|
15
18
|
ports:
|
16
19
|
- "6379:6379"
|
17
20
|
|
data/lib/sneakers/errors.rb
CHANGED
@@ -5,7 +5,7 @@ module Sneakers
|
|
5
5
|
module Handlers
|
6
6
|
#
|
7
7
|
# Maxretry uses dead letter policies on Rabbitmq to requeue and retry
|
8
|
-
# messages after failure (rejections
|
8
|
+
# messages after failure (rejections and errors). When the maximum
|
9
9
|
# number of retries is reached it will put the message on an error queue.
|
10
10
|
# This handler will only retry at the queue level. To accomplish that, the
|
11
11
|
# setup is a bit complex.
|
@@ -101,10 +101,6 @@ module Sneakers
|
|
101
101
|
handle_retry(hdr, props, msg, err)
|
102
102
|
end
|
103
103
|
|
104
|
-
def timeout(hdr, props, msg)
|
105
|
-
handle_retry(hdr, props, msg, :timeout)
|
106
|
-
end
|
107
|
-
|
108
104
|
def noop(hdr, props, msg)
|
109
105
|
|
110
106
|
end
|
data/lib/sneakers/queue.rb
CHANGED
@@ -38,7 +38,11 @@ class Sneakers::Queue
|
|
38
38
|
|
39
39
|
if exchange_name.length > 0
|
40
40
|
routing_keys.each do |key|
|
41
|
-
|
41
|
+
if @opts[:bind_arguments]
|
42
|
+
queue.bind(@exchange, routing_key: key, arguments: @opts[:bind_arguments])
|
43
|
+
else
|
44
|
+
queue.bind(@exchange, routing_key: key)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -49,7 +53,7 @@ class Sneakers::Queue
|
|
49
53
|
handler_klass = worker.opts[:handler] || Sneakers::CONFIG.fetch(:handler)
|
50
54
|
handler = handler_klass.new(@channel, queue, worker.opts)
|
51
55
|
|
52
|
-
@consumer = queue.subscribe(:
|
56
|
+
@consumer = queue.subscribe(block: false, manual_ack: @opts[:ack]) do | delivery_info, metadata, msg |
|
53
57
|
worker.do_work(delivery_info, metadata, msg, handler)
|
54
58
|
end
|
55
59
|
nil
|
@@ -72,10 +76,10 @@ class Sneakers::Queue
|
|
72
76
|
end
|
73
77
|
|
74
78
|
def create_bunny_connection
|
75
|
-
Bunny.new(@opts[:amqp], :
|
76
|
-
:
|
77
|
-
:
|
78
|
-
:
|
79
|
+
Bunny.new(@opts[:amqp], vhost: @opts[:vhost],
|
80
|
+
heartbeat: @opts[:heartbeat],
|
81
|
+
properties: @opts.fetch(:properties, {}),
|
82
|
+
logger: Sneakers::logger)
|
79
83
|
end
|
80
84
|
private :create_bunny_connection
|
81
85
|
end
|
data/lib/sneakers/version.rb
CHANGED
data/lib/sneakers/worker.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'sneakers/queue'
|
2
2
|
require 'sneakers/support/utils'
|
3
|
-
require 'timeout'
|
4
3
|
|
5
4
|
module Sneakers
|
6
5
|
module Worker
|
@@ -18,7 +17,6 @@ module Sneakers
|
|
18
17
|
opts = Sneakers::CONFIG.merge(opts)
|
19
18
|
|
20
19
|
@should_ack = opts[:ack]
|
21
|
-
@timeout_after = opts[:timeout_job_after]
|
22
20
|
@pool = pool || Concurrent::FixedThreadPool.new(opts[:threads] || Sneakers::Configuration::DEFAULTS[:threads])
|
23
21
|
@call_with_params = respond_to?(:work_with_params)
|
24
22
|
@content_type = opts[:content_type]
|
@@ -57,21 +55,15 @@ module Sneakers
|
|
57
55
|
|
58
56
|
begin
|
59
57
|
metrics.increment("work.#{self.class.name}.started")
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
res = work(deserialized_msg)
|
67
|
-
end
|
58
|
+
metrics.timing("work.#{self.class.name}.time") do
|
59
|
+
deserialized_msg = ContentType.deserialize(msg, @content_type || metadata && metadata[:content_type])
|
60
|
+
if @call_with_params
|
61
|
+
res = work_with_params(deserialized_msg, delivery_info, metadata)
|
62
|
+
else
|
63
|
+
res = work(deserialized_msg)
|
68
64
|
end
|
69
65
|
end
|
70
|
-
rescue
|
71
|
-
res = :timeout
|
72
|
-
worker_error(ex, log_msg: log_msg(msg), class: self.class.name,
|
73
|
-
message: msg, delivery_info: delivery_info, metadata: metadata)
|
74
|
-
rescue => ex
|
66
|
+
rescue StandardError, ScriptError => ex
|
75
67
|
res = :error
|
76
68
|
error = ex
|
77
69
|
worker_error(ex, log_msg: log_msg(msg), class: self.class.name,
|
@@ -83,8 +75,6 @@ module Sneakers
|
|
83
75
|
if res == :ack
|
84
76
|
# note to future-self. never acknowledge multiple (multiple=true) messages under threads.
|
85
77
|
handler.acknowledge(delivery_info, metadata, msg)
|
86
|
-
elsif res == :timeout
|
87
|
-
handler.timeout(delivery_info, metadata, msg)
|
88
78
|
elsif res == :error
|
89
79
|
handler.error(delivery_info, metadata, msg, error)
|
90
80
|
elsif res == :reject
|
data/log/.gitkeep
ADDED
File without changes
|
data/sneakers.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'sneakers/version'
|
@@ -18,22 +17,24 @@ Gem::Specification.new do |gem|
|
|
18
17
|
gem.executables = gem.files.grep(/^bin/).map { |f| File.basename(f) }
|
19
18
|
gem.test_files = gem.files.grep(/^(test|spec|features)\//)
|
20
19
|
gem.require_paths = ['lib']
|
20
|
+
|
21
21
|
gem.add_dependency 'serverengine', '~> 2.0.5'
|
22
|
-
gem.add_dependency 'bunny', '~> 2.
|
22
|
+
gem.add_dependency 'bunny', '~> 2.12'
|
23
23
|
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
24
24
|
gem.add_dependency 'thor'
|
25
|
+
gem.add_dependency 'rake'
|
25
26
|
|
26
27
|
# for integration environment (see .travis.yml and integration_spec)
|
27
28
|
gem.add_development_dependency 'rabbitmq_http_api_client'
|
28
29
|
gem.add_development_dependency 'redis'
|
29
30
|
|
31
|
+
gem.add_development_dependency 'rake'
|
32
|
+
gem.add_development_dependency 'minitest'
|
30
33
|
gem.add_development_dependency 'rr'
|
31
34
|
gem.add_development_dependency 'unparser', '0.2.2' # keep below 0.2.5 for ruby 2.0 compat.
|
32
|
-
gem.add_development_dependency 'guard-minitest'
|
33
35
|
gem.add_development_dependency 'metric_fu'
|
34
36
|
gem.add_development_dependency 'simplecov'
|
35
37
|
gem.add_development_dependency 'simplecov-rcov-text'
|
36
|
-
gem.add_development_dependency 'rake'
|
37
|
-
gem.add_development_dependency 'minitest'
|
38
38
|
gem.add_development_dependency 'guard'
|
39
|
+
gem.add_development_dependency 'guard-minitest'
|
39
40
|
end
|
data/spec/sneakers/queue_spec.rb
CHANGED
@@ -74,6 +74,17 @@ describe Sneakers::Queue do
|
|
74
74
|
q.subscribe(@mkworker)
|
75
75
|
end
|
76
76
|
|
77
|
+
it "supports setting arguments when binding" do
|
78
|
+
mock(@mkchan).queue("downloads", :durable => true) { @mkqueue }
|
79
|
+
q = Sneakers::Queue.new("downloads",
|
80
|
+
queue_vars.merge(:bind_arguments => { "os" => "linux", "cores" => 8 }))
|
81
|
+
|
82
|
+
mock(@mkqueue).bind(@mkex, :routing_key => "downloads", :arguments => { "os" => "linux", "cores" => 8 })
|
83
|
+
mock(@mkqueue).subscribe(:block => false, :manual_ack => true)
|
84
|
+
|
85
|
+
q.subscribe(@mkworker)
|
86
|
+
end
|
87
|
+
|
77
88
|
it "will use whatever handler the worker specifies" do
|
78
89
|
mock(@mkchan).queue("downloads", :durable => true) { @mkqueue }
|
79
90
|
@handler = Object.new
|
@@ -4,7 +4,7 @@ require 'sneakers'
|
|
4
4
|
require 'sneakers/runner'
|
5
5
|
|
6
6
|
describe Sneakers::Runner do
|
7
|
-
let(:logger) { Logger.new('logtest.log') }
|
7
|
+
let(:logger) { Logger.new('log/logtest.log') }
|
8
8
|
|
9
9
|
describe "with configuration that specifies a logger object" do
|
10
10
|
before do
|
@@ -27,7 +27,7 @@ describe Sneakers::Runner do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe Sneakers::RunnerConfig do
|
30
|
-
let(:logger) { Logger.new("logtest.log") }
|
30
|
+
let(:logger) { Logger.new("log/logtest.log") }
|
31
31
|
let(:runner_config) { Sneakers::Runner.new([]).instance_variable_get("@runnerconfig") }
|
32
32
|
|
33
33
|
describe "with a connection" do
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'sneakers'
|
3
|
-
require 'timeout'
|
4
3
|
require 'sneakers/handlers/oneshot'
|
5
4
|
require 'sneakers/handlers/maxretry'
|
6
5
|
require 'json'
|
@@ -77,13 +76,7 @@ describe 'Handlers' do
|
|
77
76
|
worker.do_work(@header, nil, :requeue, @handler)
|
78
77
|
end
|
79
78
|
|
80
|
-
it 'should work and handle user
|
81
|
-
mock(channel).reject(37, false)
|
82
|
-
|
83
|
-
worker.do_work(@header, nil, :timeout, @handler)
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should work and handle user-land error' do
|
79
|
+
it 'should work and handle user code error' do
|
87
80
|
mock(channel).reject(37, false)
|
88
81
|
|
89
82
|
worker.do_work(@header, nil, StandardError.new('boom!'), @handler)
|
@@ -198,7 +191,6 @@ describe 'Handlers' do
|
|
198
191
|
|
199
192
|
# it 'allows overriding the retry exchange name'
|
200
193
|
# it 'allows overriding the error exchange name'
|
201
|
-
# it 'allows overriding the retry timeout'
|
202
194
|
|
203
195
|
describe '#do_work' do
|
204
196
|
before do
|
@@ -289,36 +281,6 @@ describe 'Handlers' do
|
|
289
281
|
|
290
282
|
end
|
291
283
|
|
292
|
-
describe 'timeouts' do
|
293
|
-
describe 'more retries ahead' do
|
294
|
-
it 'should reject the message' do
|
295
|
-
mock(channel).reject(37, false)
|
296
|
-
|
297
|
-
worker.do_work(@header, @props_with_x_death, :timeout, @handler)
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
describe 'no more retries left' do
|
302
|
-
let(:max_retries) { 1 }
|
303
|
-
|
304
|
-
it 'sends the rejection to the error queue' do
|
305
|
-
mock(@header).routing_key { '#' }
|
306
|
-
mock(channel).acknowledge(37, false)
|
307
|
-
@error_exchange.extend MockPublish
|
308
|
-
|
309
|
-
worker.do_work(@header, @props_with_x_death, :timeout, @handler)
|
310
|
-
@error_exchange.called.must_equal(true)
|
311
|
-
@error_exchange.opts.must_equal({ :routing_key => '#' })
|
312
|
-
data = JSON.parse(@error_exchange.data)
|
313
|
-
data['error'].must_equal('timeout')
|
314
|
-
data['num_attempts'].must_equal(2)
|
315
|
-
data['payload'].must_equal(Base64.encode64(:timeout.to_s))
|
316
|
-
data['properties'].must_equal(Base64.encode64(@props_with_x_death.to_json))
|
317
|
-
Time.parse(data['failed_at']).wont_be_nil
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
284
|
describe 'exceptions' do
|
323
285
|
describe 'more retries ahead' do
|
324
286
|
it 'should reject the message' do
|
@@ -360,33 +322,6 @@ describe 'Handlers' do
|
|
360
322
|
it 'should work and handle noops' do
|
361
323
|
worker.do_work(@header, @props, :wait, @handler)
|
362
324
|
end
|
363
|
-
|
364
|
-
# Since we encode in json, we want to make sure if the actual payload is
|
365
|
-
# json, then it's something you can get back out.
|
366
|
-
describe 'JSON payloads' do
|
367
|
-
let(:max_retries) { 1 }
|
368
|
-
|
369
|
-
it 'properly encodes the json payload' do
|
370
|
-
mock(@header).routing_key { '#' }
|
371
|
-
mock(channel).acknowledge(37, false)
|
372
|
-
@error_exchange.extend MockPublish
|
373
|
-
|
374
|
-
payload = {
|
375
|
-
data: 'hello',
|
376
|
-
response: :timeout
|
377
|
-
}
|
378
|
-
worker.do_work(@header, @props_with_x_death, payload.to_json, @handler)
|
379
|
-
@error_exchange.called.must_equal(true)
|
380
|
-
@error_exchange.opts.must_equal({ :routing_key => '#' })
|
381
|
-
data = JSON.parse(@error_exchange.data)
|
382
|
-
data['error'].must_equal('timeout')
|
383
|
-
data['num_attempts'].must_equal(2)
|
384
|
-
data['payload'].must_equal(Base64.encode64(payload.to_json))
|
385
|
-
data['properties'].must_equal(Base64.encode64(@props_with_x_death.to_json))
|
386
|
-
end
|
387
|
-
|
388
|
-
end
|
389
|
-
|
390
325
|
end
|
391
326
|
end
|
392
327
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'sneakers'
|
3
|
-
require 'timeout'
|
4
3
|
require 'serverengine'
|
5
4
|
|
6
5
|
class DummyWorker
|
@@ -21,7 +20,6 @@ class DummyWorker
|
|
21
20
|
:ack => false,
|
22
21
|
:threads => 50,
|
23
22
|
:prefetch => 40,
|
24
|
-
:timeout_job_after => 1,
|
25
23
|
:exchange => 'dummy',
|
26
24
|
:heartbeat => 5
|
27
25
|
|
@@ -37,16 +35,6 @@ class DefaultsWorker
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
40
|
-
class TimeoutWorker
|
41
|
-
include Sneakers::Worker
|
42
|
-
from_queue 'defaults',
|
43
|
-
:timeout_job_after => 0.5,
|
44
|
-
:ack => true
|
45
|
-
|
46
|
-
def work(msg)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
38
|
class AcksWorker
|
51
39
|
include Sneakers::Worker
|
52
40
|
from_queue 'defaults',
|
@@ -110,8 +98,7 @@ end
|
|
110
98
|
class MetricsWorker
|
111
99
|
include Sneakers::Worker
|
112
100
|
from_queue 'defaults',
|
113
|
-
:ack => true
|
114
|
-
:timeout_job_after => 0.5
|
101
|
+
:ack => true
|
115
102
|
|
116
103
|
def work(msg)
|
117
104
|
metrics.increment "foobar"
|
@@ -122,8 +109,7 @@ end
|
|
122
109
|
class WithParamsWorker
|
123
110
|
include Sneakers::Worker
|
124
111
|
from_queue 'defaults',
|
125
|
-
:ack => true
|
126
|
-
:timeout_job_after => 0.5
|
112
|
+
:ack => true
|
127
113
|
|
128
114
|
def work_with_params(msg, delivery_info, metadata)
|
129
115
|
msg
|
@@ -144,21 +130,6 @@ end
|
|
144
130
|
|
145
131
|
TestPool ||= Concurrent::ImmediateExecutor
|
146
132
|
|
147
|
-
def with_test_queuefactory(ctx, ack=true, msg=nil, nowork=false)
|
148
|
-
qf = Object.new
|
149
|
-
q = Object.new
|
150
|
-
s = Object.new
|
151
|
-
hdr = Object.new
|
152
|
-
mock(qf).build_queue(anything, anything, anything) { q }
|
153
|
-
mock(q).subscribe(anything){ s }
|
154
|
-
|
155
|
-
mock(s).each(anything) { |h,b| b.call(hdr, msg) unless nowork }
|
156
|
-
mock(hdr).ack{true} if !nowork && ack
|
157
|
-
mock(hdr).reject{true} if !nowork && !ack
|
158
|
-
|
159
|
-
mock(ctx).queue_factory { qf } # should return our own
|
160
|
-
end
|
161
|
-
|
162
133
|
describe Sneakers::Worker do
|
163
134
|
before do
|
164
135
|
@queue = Object.new
|
@@ -168,7 +139,7 @@ describe Sneakers::Worker do
|
|
168
139
|
stub(@queue).exchange { @exchange }
|
169
140
|
|
170
141
|
Sneakers.clear!
|
171
|
-
Sneakers.configure(:
|
142
|
+
Sneakers.configure(daemonize: true, log: 'sneakers.log')
|
172
143
|
Sneakers::Worker.configure_metrics
|
173
144
|
end
|
174
145
|
|
@@ -202,7 +173,6 @@ describe Sneakers::Worker do
|
|
202
173
|
:workers => 4,
|
203
174
|
:log => "sneakers.log",
|
204
175
|
:pid_path => "sneakers.pid",
|
205
|
-
:timeout_job_after => 5,
|
206
176
|
:prefetch => 10,
|
207
177
|
:threads => 10,
|
208
178
|
:share_threads => false,
|
@@ -241,7 +211,6 @@ describe Sneakers::Worker do
|
|
241
211
|
:workers => 4,
|
242
212
|
:log => "sneakers.log",
|
243
213
|
:pid_path => "sneakers.pid",
|
244
|
-
:timeout_job_after => 1,
|
245
214
|
:prefetch => 40,
|
246
215
|
:threads => 50,
|
247
216
|
:share_threads => false,
|
@@ -280,7 +249,6 @@ describe Sneakers::Worker do
|
|
280
249
|
:workers => 4,
|
281
250
|
:log => "sneakers.log",
|
282
251
|
:pid_path => "sneakers.pid",
|
283
|
-
:timeout_job_after => 5,
|
284
252
|
:prefetch => 10,
|
285
253
|
:threads => 10,
|
286
254
|
:share_threads => false,
|
@@ -404,26 +372,23 @@ describe Sneakers::Worker do
|
|
404
372
|
w.do_work(header, nil, "msg", handler)
|
405
373
|
end
|
406
374
|
|
407
|
-
it "should
|
375
|
+
it "should catch script exceptions from a bad work" do
|
376
|
+
w = AcksWorker.new(@queue, TestPool.new)
|
377
|
+
mock(w).work("msg").once{ raise ScriptError }
|
408
378
|
handler = Object.new
|
409
379
|
header = Object.new
|
410
|
-
w = AcksWorker.new(@queue, TestPool.new)
|
411
|
-
mock(w).work("msg").once{ raise "foo" }
|
412
|
-
mock(w.logger).error(/error="foo" error_class=RuntimeError worker_class=AcksWorker backtrace=/)
|
413
380
|
mock(handler).error(header, nil, "msg", anything)
|
381
|
+
mock(w.logger).error(/\[Exception error="ScriptError" error_class=ScriptError worker_class=AcksWorker backtrace=.*/)
|
414
382
|
w.do_work(header, nil, "msg", handler)
|
415
383
|
end
|
416
384
|
|
417
|
-
it "should
|
418
|
-
w = TimeoutWorker.new(@queue, TestPool.new)
|
419
|
-
stub(w).work("msg"){ sleep 10 }
|
420
|
-
|
385
|
+
it "should log exceptions from workers" do
|
421
386
|
handler = Object.new
|
422
387
|
header = Object.new
|
423
|
-
|
424
|
-
mock(
|
425
|
-
mock(w.logger).error(/error="
|
426
|
-
|
388
|
+
w = AcksWorker.new(@queue, TestPool.new)
|
389
|
+
mock(w).work("msg").once{ raise "foo" }
|
390
|
+
mock(w.logger).error(/error="foo" error_class=RuntimeError worker_class=AcksWorker backtrace=/)
|
391
|
+
mock(handler).error(header, nil, "msg", anything)
|
427
392
|
w.do_work(header, nil, "msg", handler)
|
428
393
|
end
|
429
394
|
|
@@ -456,14 +421,7 @@ describe Sneakers::Worker do
|
|
456
421
|
@worker.do_work(@delivery_info, nil, :requeue, handler)
|
457
422
|
end
|
458
423
|
|
459
|
-
it "should work and handle user
|
460
|
-
handler = Object.new
|
461
|
-
mock(handler).timeout(@delivery_info, nil, :timeout)
|
462
|
-
|
463
|
-
@worker.do_work(@delivery_info, nil, :timeout, handler)
|
464
|
-
end
|
465
|
-
|
466
|
-
it "should work and handle user-land error" do
|
424
|
+
it "should work and handle user code errors" do
|
467
425
|
handler = Object.new
|
468
426
|
mock(handler).error(@delivery_info, nil, :error, anything)
|
469
427
|
|
@@ -557,7 +515,6 @@ describe Sneakers::Worker do
|
|
557
515
|
# We don't care how these are called, we're focusing on metrics here.
|
558
516
|
stub(@handler).acknowledge
|
559
517
|
stub(@handler).reject
|
560
|
-
stub(@handler).timeout
|
561
518
|
stub(@handler).error
|
562
519
|
stub(@handler).noop
|
563
520
|
|
@@ -594,12 +551,6 @@ describe Sneakers::Worker do
|
|
594
551
|
@w.do_work(@delivery_info, nil, 'msg', @handler)
|
595
552
|
end
|
596
553
|
|
597
|
-
it 'should be able to meter timeouts' do
|
598
|
-
mock(@w.metrics).increment("work.MetricsWorker.handled.timeout").once
|
599
|
-
mock(@w).work('msg'){ sleep 10 }
|
600
|
-
@w.do_work(@delivery_info, nil, 'msg', @handler)
|
601
|
-
end
|
602
|
-
|
603
554
|
it 'defaults to noop when no response is specified' do
|
604
555
|
mock(@w.metrics).increment("foobar").once
|
605
556
|
mock(@w.metrics).increment("work.MetricsWorker.handled.noop").once
|
@@ -40,7 +40,7 @@ class StubbedWorker
|
|
40
40
|
end
|
41
41
|
|
42
42
|
describe Sneakers::WorkerGroup do
|
43
|
-
let(:logger) { Logger.new('logtest.log') }
|
43
|
+
let(:logger) { Logger.new('log/logtest.log') }
|
44
44
|
let(:connection) { Bunny.new(host: 'any-host.local') }
|
45
45
|
let(:runner) { Sneakers::Runner.new([DefaultsWorker]) }
|
46
46
|
let(:runner_config) { runner.instance_variable_get('@runnerconfig') }
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sneakers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dotan Nahum
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: serverengine
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: '2.12'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
40
|
+
version: '2.12'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: concurrent-ruby
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,13 +67,13 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
|
-
type: :
|
76
|
+
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rabbitmq_http_api_client
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: redis
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,21 +109,21 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0
|
124
|
+
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: minitest
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -137,7 +137,7 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: rr
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
@@ -151,7 +151,21 @@ dependencies:
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: unparser
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.2.2
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.2.2
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: metric_fu
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
171
|
- - ">="
|
@@ -165,7 +179,7 @@ dependencies:
|
|
165
179
|
- !ruby/object:Gem::Version
|
166
180
|
version: '0'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
|
-
name: simplecov
|
182
|
+
name: simplecov
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|
170
184
|
requirements:
|
171
185
|
- - ">="
|
@@ -179,7 +193,7 @@ dependencies:
|
|
179
193
|
- !ruby/object:Gem::Version
|
180
194
|
version: '0'
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
196
|
+
name: simplecov-rcov-text
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
184
198
|
requirements:
|
185
199
|
- - ">="
|
@@ -193,7 +207,7 @@ dependencies:
|
|
193
207
|
- !ruby/object:Gem::Version
|
194
208
|
version: '0'
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
210
|
+
name: guard
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
198
212
|
requirements:
|
199
213
|
- - ">="
|
@@ -207,7 +221,7 @@ dependencies:
|
|
207
221
|
- !ruby/object:Gem::Version
|
208
222
|
version: '0'
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
|
-
name: guard
|
224
|
+
name: guard-minitest
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
212
226
|
requirements:
|
213
227
|
- - ">="
|
@@ -239,7 +253,7 @@ files:
|
|
239
253
|
- README.md
|
240
254
|
- Rakefile
|
241
255
|
- bin/sneakers
|
242
|
-
- docker-compose.
|
256
|
+
- docker-compose.yml
|
243
257
|
- examples/benchmark_worker.rb
|
244
258
|
- examples/max_retry_handler.rb
|
245
259
|
- examples/metrics_worker.rb
|
@@ -272,6 +286,7 @@ files:
|
|
272
286
|
- lib/sneakers/version.rb
|
273
287
|
- lib/sneakers/worker.rb
|
274
288
|
- lib/sneakers/workergroup.rb
|
289
|
+
- log/.gitkeep
|
275
290
|
- scripts/local_integration
|
276
291
|
- scripts/local_worker
|
277
292
|
- sneakers.gemspec
|
@@ -312,7 +327,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
327
|
version: '0'
|
313
328
|
requirements: []
|
314
329
|
rubyforge_project:
|
315
|
-
rubygems_version: 2.6.
|
330
|
+
rubygems_version: 2.6.8
|
316
331
|
signing_key:
|
317
332
|
specification_version: 4
|
318
333
|
summary: Fast background processing framework for Ruby and RabbitMQ
|