kicks 3.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![CI](https://github.com/ruby-amqp/kicks/actions/workflows/ci.yml/badge.svg)](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
|