kicks 3.0.0.pre
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 +7 -0
- data/.github/workflows/ci.yml +24 -0
- data/.gitignore +12 -0
- data/ChangeLog.md +142 -0
- data/Dockerfile +24 -0
- data/Dockerfile.slim +20 -0
- data/Gemfile +8 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +209 -0
- data/Rakefile +12 -0
- data/bin/sneakers +6 -0
- data/docker-compose.yml +24 -0
- data/examples/benchmark_worker.rb +22 -0
- data/examples/max_retry_handler.rb +68 -0
- data/examples/metrics_worker.rb +34 -0
- data/examples/middleware_worker.rb +36 -0
- data/examples/newrelic_metrics_worker.rb +40 -0
- data/examples/profiling_worker.rb +69 -0
- data/examples/sneakers.conf.rb.example +11 -0
- data/examples/title_scraper.rb +36 -0
- data/examples/workflow_worker.rb +23 -0
- data/kicks.gemspec +44 -0
- data/lib/sneakers/cli.rb +122 -0
- data/lib/sneakers/concerns/logging.rb +34 -0
- data/lib/sneakers/concerns/metrics.rb +34 -0
- data/lib/sneakers/configuration.rb +125 -0
- data/lib/sneakers/content_encoding.rb +47 -0
- data/lib/sneakers/content_type.rb +47 -0
- data/lib/sneakers/error_reporter.rb +33 -0
- data/lib/sneakers/errors.rb +2 -0
- data/lib/sneakers/handlers/maxretry.rb +219 -0
- data/lib/sneakers/handlers/oneshot.rb +26 -0
- data/lib/sneakers/metrics/logging_metrics.rb +16 -0
- data/lib/sneakers/metrics/newrelic_metrics.rb +32 -0
- data/lib/sneakers/metrics/null_metrics.rb +13 -0
- data/lib/sneakers/metrics/statsd_metrics.rb +21 -0
- data/lib/sneakers/middleware/config.rb +23 -0
- data/lib/sneakers/publisher.rb +49 -0
- data/lib/sneakers/queue.rb +87 -0
- data/lib/sneakers/runner.rb +91 -0
- data/lib/sneakers/spawner.rb +30 -0
- data/lib/sneakers/support/production_formatter.rb +11 -0
- data/lib/sneakers/support/utils.rb +18 -0
- data/lib/sneakers/tasks.rb +66 -0
- data/lib/sneakers/version.rb +3 -0
- data/lib/sneakers/worker.rb +162 -0
- data/lib/sneakers/workergroup.rb +60 -0
- data/lib/sneakers.rb +125 -0
- data/log/.gitkeep +0 -0
- data/scripts/local_integration +2 -0
- data/scripts/local_worker +3 -0
- data/spec/fixtures/integration_worker.rb +18 -0
- data/spec/fixtures/require_worker.rb +23 -0
- data/spec/gzip_helper.rb +15 -0
- data/spec/sneakers/cli_spec.rb +75 -0
- data/spec/sneakers/concerns/logging_spec.rb +39 -0
- data/spec/sneakers/concerns/metrics_spec.rb +38 -0
- data/spec/sneakers/configuration_spec.rb +97 -0
- data/spec/sneakers/content_encoding_spec.rb +81 -0
- data/spec/sneakers/content_type_spec.rb +81 -0
- data/spec/sneakers/integration_spec.rb +158 -0
- data/spec/sneakers/publisher_spec.rb +179 -0
- data/spec/sneakers/queue_spec.rb +169 -0
- data/spec/sneakers/runner_spec.rb +70 -0
- data/spec/sneakers/sneakers_spec.rb +77 -0
- data/spec/sneakers/support/utils_spec.rb +44 -0
- data/spec/sneakers/tasks/sneakers_run_spec.rb +115 -0
- data/spec/sneakers/worker_handlers_spec.rb +469 -0
- data/spec/sneakers/worker_spec.rb +712 -0
- data/spec/sneakers/workergroup_spec.rb +83 -0
- data/spec/spec_helper.rb +21 -0
- metadata +352 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ff0690a8caadf3b1b4c80039e0893f8f2484f29fec0a19278f9d855ace73355a
|
4
|
+
data.tar.gz: 4d69ee1e6a93f08df18cd2abbc8969bb2f7a854be45405a1be0c3c770c2bdd2f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e8991f96df285bfff54de0a9ce2bbcee0c8233fc81b8fc66d1ba617061650ea3badd5cc5270aaf2c95ec5103b85079e95e3095f05c7335b9681861cb44f90f0f
|
7
|
+
data.tar.gz: 43d85d3b660bd36802487769b0c518e60998227b418d427c0c69e9ce3748fc2516d574e34e5014fab3d06141d54d707f15d895e6a5648c6558a374e786e4c276
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
tests:
|
7
|
+
name: Ruby ${{ matrix.ruby-version }}
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
strategy:
|
10
|
+
matrix:
|
11
|
+
ruby-version: [3.0, 3.1, 3.2]
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v3
|
14
|
+
|
15
|
+
- name: Install Ruby ${{ matrix.ruby-version }}
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby-version }}
|
19
|
+
|
20
|
+
- name: Install dependencies
|
21
|
+
run: bundle install
|
22
|
+
|
23
|
+
- name: Run tests
|
24
|
+
run: bundle exec rake
|
data/.gitignore
ADDED
data/ChangeLog.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## Changes Between 2.12.0 and 2.13.0 (unreleased)
|
4
|
+
|
5
|
+
### Minimum Required Ruby Version
|
6
|
+
|
7
|
+
Sneakers now requires Ruby 2.5 or later.
|
8
|
+
|
9
|
+
### Content Encoding Support
|
10
|
+
|
11
|
+
Similar to already supported content type.
|
12
|
+
|
13
|
+
Contributed by @ansoncat.
|
14
|
+
|
15
|
+
GitHub issue: [#449](https://github.com/jondot/sneakers/pull/449)
|
16
|
+
|
17
|
+
## Changes Between 2.10.0 and 2.11.0
|
18
|
+
|
19
|
+
This releases includes bug fixes, support for more queue-binding options, better
|
20
|
+
management of the Bunny dependency, and improved documentation. Following is a
|
21
|
+
list of the notable changes:
|
22
|
+
|
23
|
+
### Rescue from ScriptError
|
24
|
+
|
25
|
+
Fixes a bug that would cause Sneakers workers to freeze if an exception
|
26
|
+
descending from `ScriptError`, such as `NotImplementedError`, is raised
|
27
|
+
|
28
|
+
Contributed by @sharshenov
|
29
|
+
|
30
|
+
GitHub Pull Request: [373](https://github.com/jondot/sneakers/pull/373)
|
31
|
+
|
32
|
+
### Loosen Bunny dependency to minor version
|
33
|
+
|
34
|
+
The dependency on Bunny is now pinned to the minor version instead of patch,
|
35
|
+
allowing users to benefit from non-breaking updates to Bunny without having to
|
36
|
+
wait for a Sneakers release.
|
37
|
+
|
38
|
+
Contributed by @olivierlacan
|
39
|
+
|
40
|
+
GitHub Pull Request: [#372](https://github.com/jondot/sneakers/pull/372)
|
41
|
+
|
42
|
+
### Support `:bind_arguments` on bind
|
43
|
+
|
44
|
+
It is now possible to set arguments on a queue when connecting to a headers
|
45
|
+
exchange
|
46
|
+
|
47
|
+
Contributed by @nerikj
|
48
|
+
|
49
|
+
GitHub Pull Request: [#358](https://github.com/jondot/sneakers/pull/358)
|
50
|
+
|
51
|
+
### Other contributions
|
52
|
+
|
53
|
+
This release also contains contributions from @ivan-kolmychek (bumping up Bunny
|
54
|
+
dependency), @michaelklishin (improving code style), and @darren987469 (adding
|
55
|
+
examples to the README)
|
56
|
+
|
57
|
+
## Changes Between 2.8.0 and 2.10.0
|
58
|
+
|
59
|
+
This release contains **minor breaking API changes**.
|
60
|
+
|
61
|
+
### Worker Timeouts are No Longer Enforced
|
62
|
+
|
63
|
+
This is a **breaking change** for `Sneakers::Worker` implementations.
|
64
|
+
|
65
|
+
Timeouts can be disruptive and dangerous depending on what the workers do but not having them can also
|
66
|
+
lead to operational headaches.
|
67
|
+
|
68
|
+
The outcome of [a lengthy discussion](https://github.com/jondot/sneakers/issues/343) on possible
|
69
|
+
alternatives to the timeout mechanisms is that only applications
|
70
|
+
can know where it is safe to enforce a timeout (and how).
|
71
|
+
|
72
|
+
`Sneakers::Worker` implementations are now expected to enforce timeouts
|
73
|
+
in a way that makes sense (and is safe) to them.
|
74
|
+
|
75
|
+
GitHub issues: [#343](https://github.com/jondot/sneakers/issues/343).
|
76
|
+
|
77
|
+
|
78
|
+
## Changes Between 2.6.0 and 2.7.0
|
79
|
+
|
80
|
+
This release requires Ruby 2.2 and has **breaking API changes**
|
81
|
+
around custom error handlers.
|
82
|
+
|
83
|
+
### Use Provided Connections in WorkerGroup
|
84
|
+
|
85
|
+
It is now possible to use a custom connection instance in worker groups.
|
86
|
+
|
87
|
+
Contributed by @pomnikita.
|
88
|
+
|
89
|
+
GitHub issue: [#322](https://github.com/jondot/sneakers/pull/322)
|
90
|
+
|
91
|
+
|
92
|
+
### Worker Context Available to Worker Instances
|
93
|
+
|
94
|
+
Contributed by Jason Lombardozzi.
|
95
|
+
|
96
|
+
GitHub issue: [#307](https://github.com/jondot/sneakers/pull/307)
|
97
|
+
|
98
|
+
|
99
|
+
### Ruby 2.2 Requirement
|
100
|
+
|
101
|
+
Sneakers now [requires Ruby 2.2](https://github.com/jondot/sneakers/commit/f33246a1bd3b5fe53ee662253dc5bac7864eec97).
|
102
|
+
|
103
|
+
|
104
|
+
### Bunny 2.9.x
|
105
|
+
|
106
|
+
Bunny was [upgraded](https://github.com/jondot/sneakers/commit/c7fb0bd23280082e43065d7199668486db005c13) to 2.9.x.
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
### Server Engine 2.0.5
|
111
|
+
|
112
|
+
Server Engine dependency was [upgraded to 2.0.5](https://github.com/jondot/sneakers/commit/3f60fd5e88822169fb04088f0ce5d2f94f803339).
|
113
|
+
|
114
|
+
|
115
|
+
### Refactored Publisher Connection
|
116
|
+
|
117
|
+
Contributed by Christoph Wagner.
|
118
|
+
|
119
|
+
GitHub issue: [#325](https://github.com/jondot/sneakers/pull/325)
|
120
|
+
|
121
|
+
|
122
|
+
### New Relic Reporter Migrated to the Modern API
|
123
|
+
|
124
|
+
Contributed by @adamors.
|
125
|
+
|
126
|
+
GitHub issue: [#324](https://github.com/jondot/sneakers/pull/324)
|
127
|
+
|
128
|
+
|
129
|
+
### Configuration Logged at Debug Level
|
130
|
+
|
131
|
+
To avoid potentially leaking credentials in the log.
|
132
|
+
|
133
|
+
Contributed by Kimmo Lehto.
|
134
|
+
|
135
|
+
GitHub issue: [#301](https://github.com/jondot/sneakers/pull/301).
|
136
|
+
|
137
|
+
|
138
|
+
### Comment Corrections
|
139
|
+
|
140
|
+
Contributed by Andrew Babichev
|
141
|
+
|
142
|
+
GitHub issue: [#346](https://github.com/jondot/sneakers/pull/346)
|
data/Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
FROM ruby:2.4-alpine
|
2
|
+
|
3
|
+
RUN apk add --no-cache git
|
4
|
+
|
5
|
+
RUN apk --update add --virtual build_deps \
|
6
|
+
build-base \
|
7
|
+
ruby-dev \
|
8
|
+
libc-dev \
|
9
|
+
linux-headers \
|
10
|
+
openssl-dev
|
11
|
+
|
12
|
+
WORKDIR /sneakers
|
13
|
+
|
14
|
+
COPY lib/sneakers/version.rb lib/sneakers/version.rb
|
15
|
+
|
16
|
+
COPY sneakers.gemspec .
|
17
|
+
|
18
|
+
COPY Gemfile* ./
|
19
|
+
|
20
|
+
RUN bundle install --retry=3
|
21
|
+
|
22
|
+
COPY . .
|
23
|
+
|
24
|
+
CMD rake test
|
data/Dockerfile.slim
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
FROM ruby:2.3-alpine
|
2
|
+
|
3
|
+
RUN apk add --no-cache git
|
4
|
+
|
5
|
+
ADD . /sneakers
|
6
|
+
|
7
|
+
WORKDIR /sneakers
|
8
|
+
|
9
|
+
RUN apk --update add --virtual build_deps \
|
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
|
19
|
+
|
20
|
+
CMD rake test
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013-2016 Dotan Nahum
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# Kicks, né Sneakers
|
2
|
+
|
3
|
+
[](https://github.com/ruby-amqp/kicks/actions/workflows/ci.yml)
|
4
|
+
|
5
|
+
```
|
6
|
+
__
|
7
|
+
,--' >
|
8
|
+
`=====
|
9
|
+
|
10
|
+
```
|
11
|
+
|
12
|
+
## What is Kicks?
|
13
|
+
|
14
|
+
Kicks is a high-performance RabbitMQ background processing framework for
|
15
|
+
Ruby, originally developed by @jondot 👏 under the name of [Sneakers](https://github.com/jondot/sneakers).
|
16
|
+
The original repo was abandoned by the person who has exclusive control
|
17
|
+
over the RubyGems project, so the community of users has decided to move it
|
18
|
+
to this "fork" (continuation) under the new name.
|
19
|
+
|
20
|
+
By virtue of its Sneakers lineage, Kicks is a mature project that has been around since 2016.
|
21
|
+
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Add this line to your application's Gemfile:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# Important: this name will change once Kicks 3.0.0 (the initial release) is published
|
29
|
+
gem 'sneakers'
|
30
|
+
```
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
```shell-session
|
35
|
+
$ bundle
|
36
|
+
```
|
37
|
+
|
38
|
+
Or install it yourself as:
|
39
|
+
|
40
|
+
```shell-session
|
41
|
+
$ gem install sneakers
|
42
|
+
```
|
43
|
+
|
44
|
+
## Documentation
|
45
|
+
|
46
|
+
A quick start guide is available in the section below.
|
47
|
+
|
48
|
+
Visit the [wiki](https://github.com/jondot/sneakers/wiki) for more detailed
|
49
|
+
documentation and [GitHub releases](https://github.com/jondot/sneakers/releases) for release
|
50
|
+
notes.
|
51
|
+
|
52
|
+
A [change log](./ChangeLog.md) is also available.
|
53
|
+
|
54
|
+
## Quick start
|
55
|
+
|
56
|
+
Set up a Gemfile
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
source 'https://rubygems.org'
|
60
|
+
gem 'sneakers'
|
61
|
+
gem 'json'
|
62
|
+
gem 'redis'
|
63
|
+
```
|
64
|
+
|
65
|
+
How do we add a worker? Firstly create a file and name it as `boot.rb`
|
66
|
+
then create a worker named as `Processor`.
|
67
|
+
|
68
|
+
> touch boot.rb
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require 'sneakers'
|
72
|
+
require 'redis'
|
73
|
+
require 'json'
|
74
|
+
|
75
|
+
$redis = Redis.new
|
76
|
+
|
77
|
+
class Processor
|
78
|
+
include Sneakers::Worker
|
79
|
+
from_queue :logs
|
80
|
+
|
81
|
+
def work(msg)
|
82
|
+
err = JSON.parse(msg)
|
83
|
+
if err["type"] == "error"
|
84
|
+
$redis.incr "processor:#{err["error"]}"
|
85
|
+
end
|
86
|
+
|
87
|
+
ack!
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
Let's test it out quickly from the command line:
|
93
|
+
|
94
|
+
```shell-session
|
95
|
+
$ sneakers work Processor --require boot.rb
|
96
|
+
```
|
97
|
+
|
98
|
+
We just told Sneakers to spawn a worker named `Processor`, but first `--require` a file that we dedicate to setting up environment, including workers and what-not.
|
99
|
+
|
100
|
+
If you go to your RabbitMQ admin now, you'll see a new queue named `logs` was created. Push a couple messages like below:
|
101
|
+
|
102
|
+
```javascript
|
103
|
+
{
|
104
|
+
"type": "error",
|
105
|
+
"message": "HALP!",
|
106
|
+
"error": "CODE001"
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
Publish a message with the [bunny](https://github.com/ruby-amqp/bunny) gem RabbitMQ client:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
require 'bunny'
|
114
|
+
|
115
|
+
conn = Bunny.new
|
116
|
+
conn.start
|
117
|
+
|
118
|
+
ch = conn.create_channel
|
119
|
+
ch.default_exchange.publish({ type: 'error', message: 'HALP!', error: 'CODE001' }.to_json, routing_key: 'logs')
|
120
|
+
|
121
|
+
conn.close
|
122
|
+
```
|
123
|
+
|
124
|
+
And this is the output you should see at your terminal.
|
125
|
+
|
126
|
+
```
|
127
|
+
2013-10-11T19:26:36Z p-4718 t-ovqgyb31o DEBUG: [worker-logs:1:213mmy][#<Thread:0x007fae6b05cc58>][logs][{:prefetch=>10, :durable=>true, :ack=>true, :heartbeat_interval=>2, :exchange=>"sneakers"}] Working off: log log
|
128
|
+
2013-10-11T19:26:36Z p-4718 t-ovqgyrxu4 INFO: log log
|
129
|
+
2013-10-11T19:26:40Z p-4719 t-ovqgyb364 DEBUG: [worker-logs:1:h23iit][#<Thread:0x007fae6b05cd98>][logs][{:prefetch=>10, :durable=>true, :ack=>true, :heartbeat_interval=>2, :exchange=>"sneakers"}] Working off: log log
|
130
|
+
2013-10-11T19:26:40Z p-4719 t-ovqgyrx8g INFO: log log
|
131
|
+
```
|
132
|
+
|
133
|
+
We'll count errors and error types with Redis.
|
134
|
+
|
135
|
+
``` shell-session
|
136
|
+
$ redis-cli monitor
|
137
|
+
1381520329.888581 [0 127.0.0.1:49182] "incr" "processor:CODE001"
|
138
|
+
```
|
139
|
+
|
140
|
+
We're basically done with the ceremonies and all is left is to do some real work.
|
141
|
+
|
142
|
+
### Looking at metrics
|
143
|
+
|
144
|
+
Let's use the `logging_metrics` provider just for the sake of fun of seeing the metrics as they happen.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# boot.rb
|
148
|
+
require 'sneakers'
|
149
|
+
require 'redis'
|
150
|
+
require 'json'
|
151
|
+
require 'sneakers/metrics/logging_metrics'
|
152
|
+
Sneakers.configure(metrics: Sneakers::Metrics::LoggingMetrics.new)
|
153
|
+
|
154
|
+
# ... rest of code
|
155
|
+
```
|
156
|
+
|
157
|
+
Now push a message again and you'll see:
|
158
|
+
|
159
|
+
```
|
160
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: INC: work.Processor.started
|
161
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: TIME: work.Processor.time 0.00242
|
162
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: INC: work.Processor.handled.ack
|
163
|
+
```
|
164
|
+
|
165
|
+
Which increments `started` and `handled.ack`, and times the work unit.
|
166
|
+
|
167
|
+
From here, you can continue over to the
|
168
|
+
[Wiki](https://github.com/jondot/sneakers/wiki)
|
169
|
+
|
170
|
+
# Docker
|
171
|
+
|
172
|
+
If you use Docker, there's some benefits to be had and you can use both
|
173
|
+
`docker` and `docker-compose` with this project, in order to run tests,
|
174
|
+
integration tests or a sample worker without setting up RabbitMQ or the
|
175
|
+
environment needed locally on your development box.
|
176
|
+
|
177
|
+
* To build a container run `docker build . -t sneakers_sneakers`
|
178
|
+
* To run non-integration tests within a docker container, run `docker run --rm
|
179
|
+
sneakers_sneakers:latest`
|
180
|
+
* To run full integration tests within a docker topology including RabbitMQ,
|
181
|
+
Redis (for integration worker) run `scripts/local_integration`, which will
|
182
|
+
use docker-compose to orchestrate the topology and the sneakers Docker image
|
183
|
+
to run the tests
|
184
|
+
* To run a sample worker within Docker, try the `TitleScraper` example by
|
185
|
+
running `script/local_worker`. This will use docker-compose as well. It will
|
186
|
+
also help you get a feeling for how to run Sneakers in a Docker based
|
187
|
+
production environment
|
188
|
+
* Use `Dockerfile.slim` instead of `Dockerfile` for production docker builds.
|
189
|
+
It generates a more compact image, while the "regular" `Dockerfile` generates
|
190
|
+
a fatter image - yet faster to iterate when developing
|
191
|
+
|
192
|
+
# Compatibility
|
193
|
+
|
194
|
+
* Sneakers main branch: Ruby 3.0+
|
195
|
+
* Sneakers 2.7.x and later (using Bunny 2.9): Ruby 2.2.x
|
196
|
+
* Sneakers 1.1.x and later (using Bunny 2.x): Ruby 2.x
|
197
|
+
* Sneakers 1.x.x and earlier: Ruby 1.9.x, 2.x
|
198
|
+
|
199
|
+
# Contributing
|
200
|
+
|
201
|
+
Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
|
202
|
+
|
203
|
+
### Thanks:
|
204
|
+
|
205
|
+
To all Sneakers [Contributors](https://github.com/jondot/sneakers/graphs/contributors) - you make this happen, thanks!
|
206
|
+
|
207
|
+
# Copyright
|
208
|
+
|
209
|
+
Copyright (c) 2015-2018 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details.
|
data/Rakefile
ADDED
data/bin/sneakers
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
version: '3'
|
2
|
+
|
3
|
+
services:
|
4
|
+
sneakers:
|
5
|
+
build: .
|
6
|
+
volumes:
|
7
|
+
- .:/sneakers
|
8
|
+
depends_on:
|
9
|
+
- rabbitmq
|
10
|
+
- redis
|
11
|
+
environment:
|
12
|
+
- RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
|
13
|
+
|
14
|
+
rabbitmq:
|
15
|
+
image: rabbitmq:management-alpine
|
16
|
+
ports:
|
17
|
+
- "5672:5672"
|
18
|
+
- "15672:15672"
|
19
|
+
|
20
|
+
redis:
|
21
|
+
image: redis:alpine
|
22
|
+
ports:
|
23
|
+
- "6379:6379"
|
24
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
|
4
|
+
class BenchmarkWorker
|
5
|
+
include Sneakers::Worker
|
6
|
+
from_queue 'downloads',
|
7
|
+
exchange_options: { durable: false },
|
8
|
+
queue_options: { durable: false },
|
9
|
+
:ack => true,
|
10
|
+
:threads => 50,
|
11
|
+
:prefetch => 50,
|
12
|
+
:timeout_job_after => 1,
|
13
|
+
:exchange => 'dummy',
|
14
|
+
:heartbeat => 5,
|
15
|
+
:amqp_heartbeat => 10
|
16
|
+
def work(msg)
|
17
|
+
ack!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
require 'sneakers/runner'
|
4
|
+
require 'sneakers/handlers/maxretry'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
Sneakers.configure(:handler => Sneakers::Handlers::Maxretry,
|
8
|
+
:workers => 1,
|
9
|
+
:threads => 1,
|
10
|
+
:prefetch => 1,
|
11
|
+
:exchange => 'sneakers',
|
12
|
+
:exchange_options => { :type => 'topic', durable: true },
|
13
|
+
:routing_key => ['#', 'something']
|
14
|
+
)
|
15
|
+
Sneakers.logger.level = Logger::DEBUG
|
16
|
+
|
17
|
+
WORKER_OPTIONS = {
|
18
|
+
:ack => true,
|
19
|
+
:threads => 1,
|
20
|
+
:prefetch => 1,
|
21
|
+
:timeout_job_after => 60,
|
22
|
+
:heartbeat => 5,
|
23
|
+
:amqp_heartbeat => 10,
|
24
|
+
:retry_timeout => 5000
|
25
|
+
}
|
26
|
+
|
27
|
+
# Example of how to write a retry worker. If your rabbit system is empty, then
|
28
|
+
# you must run this twice. Once to setup the exchanges, queues and bindings a
|
29
|
+
# second time to have the sent message end up on the downloads queue.
|
30
|
+
#
|
31
|
+
# Run this via:
|
32
|
+
# bundle exec ruby examples/max_retry_handler.rb
|
33
|
+
#
|
34
|
+
class MaxRetryWorker
|
35
|
+
include Sneakers::Worker
|
36
|
+
from_queue 'downloads', WORKER_OPTIONS
|
37
|
+
|
38
|
+
def work(msg)
|
39
|
+
logger.info("MaxRetryWorker rejecting msg: #{msg.inspect}")
|
40
|
+
|
41
|
+
# We always want to reject to see if we do the proper timeout
|
42
|
+
reject!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Example of a worker on the same exchange that does not fail, so it should only
|
47
|
+
# see the message once.
|
48
|
+
class SucceedingWorker
|
49
|
+
include Sneakers::Worker
|
50
|
+
from_queue 'uploads', WORKER_OPTIONS
|
51
|
+
|
52
|
+
def work(msg)
|
53
|
+
logger.info("SucceedingWorker succeeding on msg: #{msg.inspect}")
|
54
|
+
ack!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
messages = 1
|
59
|
+
puts "feeding messages in"
|
60
|
+
messages.times {
|
61
|
+
Sneakers.publish(" -- message -- ",
|
62
|
+
:to_queue => 'anywhere',
|
63
|
+
:persistence => true)
|
64
|
+
}
|
65
|
+
puts "done"
|
66
|
+
|
67
|
+
r = Sneakers::Runner.new([MaxRetryWorker, SucceedingWorker])
|
68
|
+
r.run
|
@@ -0,0 +1,34 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
require 'sneakers/runner'
|
4
|
+
require 'sneakers/metrics/logging_metrics'
|
5
|
+
require 'open-uri'
|
6
|
+
|
7
|
+
|
8
|
+
class MetricsWorker
|
9
|
+
include Sneakers::Worker
|
10
|
+
|
11
|
+
from_queue 'downloads'
|
12
|
+
|
13
|
+
def work(msg)
|
14
|
+
title = extract_title(open(msg))
|
15
|
+
logger.info "FOUND <#{title}>"
|
16
|
+
ack!
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def extract_title(html)
|
22
|
+
html =~ /<title>(.*?)<\/title>/
|
23
|
+
$1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
Sneakers.configure(:metrics => Sneakers::Metrics::LoggingMetrics.new)
|
29
|
+
r = Sneakers::Runner.new([ MetricsWorker ])
|
30
|
+
r.run
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
require 'sneakers/runner'
|
4
|
+
|
5
|
+
class MiddlewareWorker
|
6
|
+
include Sneakers::Worker
|
7
|
+
|
8
|
+
from_queue 'middleware-demo',
|
9
|
+
ack: false
|
10
|
+
|
11
|
+
def work(message)
|
12
|
+
puts "******** MiddlewareWorker -> #{message}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class DemoMiddleware
|
17
|
+
def initialize(app, *args)
|
18
|
+
@app = app
|
19
|
+
@args = args
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(deserialized_msg, delivery_info, metadata, handler)
|
23
|
+
puts "******** DemoMiddleware - before; args #{@args}"
|
24
|
+
res = @app.call(deserialized_msg, delivery_info, metadata, handler)
|
25
|
+
puts "******** DemoMiddleware - after"
|
26
|
+
|
27
|
+
res
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Sneakers.configure
|
32
|
+
Sneakers.middleware.use(DemoMiddleware, foo: :bar)
|
33
|
+
|
34
|
+
Sneakers.publish("{}", :to_queue => 'middleware-demo')
|
35
|
+
r = Sneakers::Runner.new([MiddlewareWorker])
|
36
|
+
r.run
|