kicks 3.2.0 → 3.4.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/.github/workflows/ci.yml +36 -7
- data/AGENTS.md +116 -0
- data/CLAUDE.md +1 -0
- data/ChangeLog.md +54 -4
- data/GEMINI.md +1 -0
- data/README.md +9 -4
- data/kicks.gemspec +2 -2
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +1 -1
- data/lib/sneakers/configuration.rb +6 -1
- data/lib/sneakers/handlers/maxretry.rb +22 -6
- data/lib/sneakers/version.rb +1 -1
- data/lib/sneakers/worker.rb +1 -1
- data/lib/sneakers.rb +3 -4
- data/spec/sneakers/worker_handlers_spec.rb +114 -0
- data/spec/sneakers/worker_spec.rb +20 -3
- metadata +9 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3ecabfdb6983f2a20237a579d28d78cf868ada1979b4cd4b0b697d36b02a260
|
|
4
|
+
data.tar.gz: b8734c3b4a29ee2e2f5d735b0bbf9862391006506372f29b608af46470ec05fe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 337a21db50e4ff7f8931abdf9eb1ab91a3a3f30d66b242e823e2a62bb93b162260aaab6c1d1b09f239fac46f1f837c2d8d0c9624e21b9500adc64076c20f123d
|
|
7
|
+
data.tar.gz: 342e9a4ba8bed410c80211cac9df5e1558cbae7e03cf774b3c5d559a3daa75096c3748a2242cb09e35f2194aa2086995cd6f0d6e44058def877b7d83ed6163eb
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -1,22 +1,51 @@
|
|
|
1
1
|
name: CI
|
|
2
2
|
|
|
3
|
-
on:
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "main"
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- "main"
|
|
4
10
|
|
|
5
11
|
jobs:
|
|
6
12
|
tests:
|
|
7
|
-
name: Ruby ${{ matrix.ruby
|
|
13
|
+
name: RabbitMQ ${{ matrix.rabbitmq }}, Ruby ${{ matrix.ruby }}
|
|
8
14
|
runs-on: ubuntu-latest
|
|
15
|
+
|
|
9
16
|
strategy:
|
|
17
|
+
fail-fast: false
|
|
10
18
|
matrix:
|
|
11
|
-
ruby
|
|
19
|
+
ruby:
|
|
20
|
+
- "4.0"
|
|
21
|
+
- "3.4"
|
|
22
|
+
- "3.3"
|
|
23
|
+
- "3.2"
|
|
24
|
+
- "3.1"
|
|
25
|
+
rabbitmq:
|
|
26
|
+
- "4.2"
|
|
27
|
+
- "4.1"
|
|
28
|
+
- "4.0"
|
|
29
|
+
- "3.13"
|
|
30
|
+
|
|
31
|
+
services:
|
|
32
|
+
rabbitmq:
|
|
33
|
+
image: rabbitmq:${{ matrix.rabbitmq }}-management
|
|
34
|
+
ports:
|
|
35
|
+
- 5672:5672
|
|
36
|
+
- 15672:15672
|
|
37
|
+
|
|
12
38
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
39
|
+
- uses: actions/checkout@v7
|
|
14
40
|
|
|
15
|
-
- name:
|
|
41
|
+
- name: Set up Ruby ${{ matrix.ruby }}
|
|
16
42
|
uses: ruby/setup-ruby@v1
|
|
17
43
|
with:
|
|
18
|
-
ruby-version: ${{ matrix.ruby
|
|
19
|
-
bundler-cache: true
|
|
44
|
+
ruby-version: ${{ matrix.ruby }}
|
|
45
|
+
bundler-cache: true
|
|
46
|
+
|
|
47
|
+
- name: Wait for RabbitMQ to start
|
|
48
|
+
run: sleep 10
|
|
20
49
|
|
|
21
50
|
- name: Run tests
|
|
22
51
|
run: bundle exec rake
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Instructions for AI Agents
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Kicks is a fast background processing framework for Ruby and RabbitMQ.
|
|
6
|
+
It was originally developed under the name [Sneakers](https://github.com/jondot/sneakers)
|
|
7
|
+
and later renamed and moved to [`ruby-amqp/kicks`](https://github.com/ruby-amqp/kicks).
|
|
8
|
+
|
|
9
|
+
Its key dependency is [Bunny](https://github.com/ruby-amqp/bunny), a Ruby AMQP 0-9-1 client for RabbitMQ.
|
|
10
|
+
|
|
11
|
+
## Target Ruby Version
|
|
12
|
+
|
|
13
|
+
This library targets Ruby 3.1 and later versions.
|
|
14
|
+
|
|
15
|
+
## Build and Test
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bundle install
|
|
19
|
+
|
|
20
|
+
bundle exec rake test
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
To run a specific test file:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle exec ruby -Ilib -Ispec spec/sneakers/queue_spec.rb
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Key Files
|
|
30
|
+
|
|
31
|
+
### Core
|
|
32
|
+
|
|
33
|
+
* `lib/sneakers.rb`: top-level module, global configuration, logger setup
|
|
34
|
+
* `lib/sneakers/queue.rb`: Bunny connection and channel lifecycle, queue and exchange declaration, consumer subscription
|
|
35
|
+
* `lib/sneakers/worker.rb`: `Sneakers::Worker` module included by worker classes; message dispatch, acknowledgement, error handling
|
|
36
|
+
* `lib/sneakers/publisher.rb`: message publishing with its own Bunny connection
|
|
37
|
+
* `lib/sneakers/runner.rb`: worker process runner built on ServerEngine
|
|
38
|
+
* `lib/sneakers/spawner.rb`: forks worker groups into separate processes
|
|
39
|
+
* `lib/sneakers/workergroup.rb`: manages a group of workers sharing a connection
|
|
40
|
+
* `lib/sneakers/configuration.rb`: configuration defaults and option merging
|
|
41
|
+
* `lib/sneakers/content_type.rb`: pluggable content type serialization/deserialization
|
|
42
|
+
* `lib/sneakers/content_encoding.rb`: pluggable content encoding (e.g. gzip)
|
|
43
|
+
* `lib/sneakers/error_reporter.rb`: error reporting interface
|
|
44
|
+
* `lib/sneakers/cli.rb`: Thor-based CLI (`sneakers work`)
|
|
45
|
+
* `lib/sneakers/tasks.rb`: Rake tasks for running workers
|
|
46
|
+
* `lib/sneakers/version.rb`: the `Sneakers::VERSION` constant
|
|
47
|
+
|
|
48
|
+
### Handlers
|
|
49
|
+
|
|
50
|
+
* `lib/sneakers/handlers/oneshot.rb`: basic handler that acks/rejects once (default)
|
|
51
|
+
* `lib/sneakers/handlers/maxretry.rb`: dead-letter-based retry with configurable max attempts
|
|
52
|
+
|
|
53
|
+
### Metrics
|
|
54
|
+
|
|
55
|
+
* `lib/sneakers/metrics/null_metrics.rb`: no-op (default)
|
|
56
|
+
* `lib/sneakers/metrics/logging_metrics.rb`: logs metric events
|
|
57
|
+
* `lib/sneakers/metrics/statsd_metrics.rb`: StatsD integration
|
|
58
|
+
* `lib/sneakers/metrics/newrelic_metrics.rb`: New Relic integration
|
|
59
|
+
|
|
60
|
+
### ActiveJob
|
|
61
|
+
|
|
62
|
+
* `lib/active_job/queue_adapters/sneakers_adapter.rb`: Rails ActiveJob adapter
|
|
63
|
+
|
|
64
|
+
### Testing
|
|
65
|
+
|
|
66
|
+
* `spec/sneakers/`: test files that mirror the `lib/sneakers/` structure
|
|
67
|
+
* `spec/sneakers/integration_spec.rb`: integration tests requiring a running RabbitMQ node and `INTEGRATION=1`
|
|
68
|
+
|
|
69
|
+
## Comments
|
|
70
|
+
|
|
71
|
+
* Only add important comments that express the non-obvious intent, both in tests and in the implementation
|
|
72
|
+
* Keep the comments short
|
|
73
|
+
* Pay attention to the grammar of your comments, including punctuation, full stops, articles, and so on
|
|
74
|
+
|
|
75
|
+
## Change Log
|
|
76
|
+
|
|
77
|
+
If asked to perform change log updates, consult and modify `ChangeLog.md` and stick to its
|
|
78
|
+
existing writing style.
|
|
79
|
+
|
|
80
|
+
## Releases
|
|
81
|
+
|
|
82
|
+
### How to Roll (Produce) a New Release
|
|
83
|
+
|
|
84
|
+
Suppose the current development version in `ChangeLog.md` has
|
|
85
|
+
a `## Changes Between X.Y.0 and X.(Y+1).0 (in development)` section at the top.
|
|
86
|
+
|
|
87
|
+
To produce a new release:
|
|
88
|
+
|
|
89
|
+
1. Update `ChangeLog.md`: replace `(in development)` with today's date, e.g. `(Mar 30, 2026)`. Make sure all notable changes since the previous release are listed
|
|
90
|
+
2. Update the version in `lib/sneakers/version.rb` to match (remove the `.pre` suffix)
|
|
91
|
+
3. Commit with the message `X.(Y+1).0` (just the version number, nothing else)
|
|
92
|
+
4. Tag the commit: `git tag vX.(Y+1).0`
|
|
93
|
+
5. Bump the dev version: add a new `## Changes Between X.(Y+1).0 and X.(Y+2).0 (in development)` section to `ChangeLog.md` with `No (documented) changes yet.` underneath, and update `lib/sneakers/version.rb` to the next dev version with a `.pre` suffix
|
|
94
|
+
6. Commit with the message `Back to dev version`
|
|
95
|
+
7. Push: `git push && git push origin vX.(Y+1).0`
|
|
96
|
+
|
|
97
|
+
## Git Instructions
|
|
98
|
+
|
|
99
|
+
* Do not commit changes automatically without explicit permission to do so
|
|
100
|
+
* Never add yourself to the list of commit co-authors
|
|
101
|
+
* Never mention yourself in commit messages in any way (no "Generated by", no AI tool links, etc)
|
|
102
|
+
|
|
103
|
+
## Style Guide
|
|
104
|
+
|
|
105
|
+
* Never add full stops to Markdown list items
|
|
106
|
+
|
|
107
|
+
## After Completing a Task
|
|
108
|
+
|
|
109
|
+
### Iterative Reviews
|
|
110
|
+
|
|
111
|
+
After completing a task, perform up to thirty iterative reviews of your changes.
|
|
112
|
+
In every iteration, look for meaningful improvements that were missed, for gaps in test coverage,
|
|
113
|
+
and for deviations from the instructions in this file.
|
|
114
|
+
|
|
115
|
+
If no meaningful improvements are found for three iterations in a row,
|
|
116
|
+
report it and stop iterating.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
data/ChangeLog.md
CHANGED
|
@@ -1,16 +1,66 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## Changes Between 3.
|
|
3
|
+
## Changes Between 3.3.0 and 3.4.0 (Jul 31, 2026)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Bunny 3.x
|
|
6
|
+
|
|
7
|
+
Kicks now depends on Bunny `3.x`.
|
|
8
|
+
|
|
9
|
+
Bunny 3.0 removed `Bunny::VersionedDeliveryTag`, changed the third argument of
|
|
10
|
+
`Bunny::Channel#initialize` to an options hash, and moved topology recovery to
|
|
11
|
+
`Bunny::Session`. None of these affect the Kicks API.
|
|
12
|
+
|
|
13
|
+
GitHub issue: [#45](https://github.com/ruby-amqp/kicks/issues/45)
|
|
14
|
+
|
|
15
|
+
### Minimum Required Ruby Version
|
|
16
|
+
|
|
17
|
+
Kicks now requires Ruby `3.1` or later.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Changes Between 3.2.0 and 3.3.0 (Mar 31, 2026)
|
|
21
|
+
|
|
22
|
+
### Queue Type Inheritance for Retry and Error Queues
|
|
23
|
+
|
|
24
|
+
The `maxretry` handler now inherits the queue type from the worker queue's
|
|
25
|
+
arguments when declaring retry and error queues.
|
|
26
|
+
|
|
27
|
+
This can be overridden with the `:retry_queue_arguments` option.
|
|
28
|
+
|
|
29
|
+
GitHub issue: [#38](https://github.com/ruby-amqp/kicks/pull/38)
|
|
30
|
+
|
|
31
|
+
Contributed by @chris72205.
|
|
32
|
+
|
|
33
|
+
### Improved Bunny Exception Handling for Consumers
|
|
34
|
+
|
|
35
|
+
Contributed by @shashankmehra.
|
|
36
|
+
|
|
37
|
+
GitHub issue: [#35](https://github.com/ruby-amqp/kicks/pull/35)
|
|
38
|
+
|
|
39
|
+
### Improved Logger Configuration
|
|
40
|
+
|
|
41
|
+
Contributed by @cdhagmann.
|
|
42
|
+
|
|
43
|
+
GitHub issue: [#34](https://github.com/ruby-amqp/kicks/pull/34)
|
|
44
|
+
|
|
45
|
+
### Bunny Version Bump
|
|
46
|
+
|
|
47
|
+
Kicks now requires the latest (at the time of writing) Bunny `2.24.x`.
|
|
48
|
+
|
|
49
|
+
### Support Rails 7.2
|
|
50
|
+
|
|
51
|
+
Contributed by @sekrett.
|
|
52
|
+
|
|
53
|
+
GitHub issue: [#32](https://github.com/ruby-amqp/kicks/pull/32)
|
|
6
54
|
|
|
7
55
|
|
|
8
56
|
## Changes Between 3.1.0 and 3.2.0 (Jan 26, 2025)
|
|
9
57
|
|
|
10
58
|
### Improved Support for Bring-Your-Own-Connection (BYOC)
|
|
11
59
|
|
|
12
|
-
Kicks now supports a callable (e.g. a proc)
|
|
13
|
-
and managed Bunny connection.
|
|
60
|
+
Kicks now supports passing in a callable (e.g. a proc) instead of an externally-initialized
|
|
61
|
+
and managed Bunny connection.
|
|
62
|
+
|
|
63
|
+
In this case, it is entirely up to the caller
|
|
14
64
|
to configure the connection and call `Bunny::Session#start` on it
|
|
15
65
|
at the right moment.
|
|
16
66
|
|
data/GEMINI.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
data/README.md
CHANGED
|
@@ -20,6 +20,11 @@ to this "fork" (continuation) under the new name.
|
|
|
20
20
|
By virtue of its Sneakers lineage, Kicks is a mature project that has been around since 2016.
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
## Supported Ruby Versions
|
|
24
|
+
|
|
25
|
+
Kicks `3.4.x` and later series target Ruby `3.1` and later versions.
|
|
26
|
+
|
|
27
|
+
|
|
23
28
|
## Installation
|
|
24
29
|
|
|
25
30
|
Add this line to your application's Gemfile:
|
|
@@ -191,9 +196,9 @@ environment needed locally on your development box.
|
|
|
191
196
|
|
|
192
197
|
# Compatibility
|
|
193
198
|
|
|
194
|
-
* Kicks main branch: Ruby 3.
|
|
195
|
-
* Kicks 3.
|
|
196
|
-
* Kicks 3.0.x: Ruby 2.5+
|
|
199
|
+
* Kicks main branch: Ruby 3.1+
|
|
200
|
+
* Kicks 3.4.x and later (using Bunny 3.x): Ruby 3.1+
|
|
201
|
+
* Kicks 3.0.x through 3.3.x (using Bunny 2.x): Ruby 2.5+
|
|
197
202
|
* Sneakers 2.7.x and later (using Bunny 2.9): Ruby 2.2.x
|
|
198
203
|
* Sneakers 1.1.x and later (using Bunny 2.x): Ruby 2.x
|
|
199
204
|
* Sneakers 1.x.x and earlier: Ruby 1.9.x, 2.x
|
|
@@ -212,6 +217,6 @@ See [LICENSE](LICENSE.txt) for further details.
|
|
|
212
217
|
|
|
213
218
|
## Copyright
|
|
214
219
|
|
|
215
|
-
Copyright (c) 2023-
|
|
220
|
+
Copyright (c) 2023-2026 Kicks contributors.
|
|
216
221
|
|
|
217
222
|
Copyright (c) 2015-2023 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot).
|
data/kicks.gemspec
CHANGED
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
|
|
|
15
15
|
gem.homepage = 'https://github.com/ruby-amqp/kicks'
|
|
16
16
|
gem.metadata = { "source_code_uri" => "https://github.com/ruby-amqp/kicks" }
|
|
17
17
|
gem.license = 'MIT'
|
|
18
|
-
gem.required_ruby_version = Gem::Requirement.new(">=
|
|
18
|
+
gem.required_ruby_version = Gem::Requirement.new(">= 3.1")
|
|
19
19
|
|
|
20
20
|
gem.files = `git ls-files`.split($/).reject { |f| f == 'Gemfile.lock' }
|
|
21
21
|
gem.executables = gem.files.grep(/^bin/).
|
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
|
|
|
25
25
|
gem.require_paths = ['lib']
|
|
26
26
|
|
|
27
27
|
gem.add_dependency 'serverengine', '~> 2.1'
|
|
28
|
-
gem.add_dependency 'bunny', '~>
|
|
28
|
+
gem.add_dependency 'bunny', '~> 3.0'
|
|
29
29
|
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
|
30
30
|
gem.add_dependency 'thor'
|
|
31
31
|
gem.add_dependency 'rake', '>= 12.3', '< 14.0'
|
|
@@ -8,7 +8,7 @@ module ActiveJob
|
|
|
8
8
|
# To use Sneakers set the queue_adapter config to +:sneakers+.
|
|
9
9
|
#
|
|
10
10
|
# Rails.application.config.active_job.queue_adapter = :sneakers
|
|
11
|
-
class SneakersAdapter
|
|
11
|
+
class SneakersAdapter < (const_defined?(:AbstractAdapter) ? AbstractAdapter : Object)
|
|
12
12
|
def initialize
|
|
13
13
|
@monitor = Monitor.new
|
|
14
14
|
end
|
|
@@ -5,7 +5,7 @@ module Sneakers
|
|
|
5
5
|
class Configuration
|
|
6
6
|
|
|
7
7
|
extend Forwardable
|
|
8
|
-
def_delegators :@hash, :to_hash, :[], :[]=, :==, :fetch, :delete, :has_key?, :dig
|
|
8
|
+
def_delegators :@hash, :to_hash, :[], :[]=, :==, :fetch, :delete, :has_key?, :dig, :slice
|
|
9
9
|
|
|
10
10
|
EXCHANGE_OPTION_DEFAULTS = {
|
|
11
11
|
:type => :direct,
|
|
@@ -35,6 +35,11 @@ module Sneakers
|
|
|
35
35
|
:log => STDOUT,
|
|
36
36
|
:pid_path => 'sneakers.pid',
|
|
37
37
|
:amqp_heartbeat => 30,
|
|
38
|
+
|
|
39
|
+
# Default values from serverengine
|
|
40
|
+
:log_rotate_age => 5,
|
|
41
|
+
:log_rotate_size => 1048576,
|
|
42
|
+
:log_level => 'debug',
|
|
38
43
|
|
|
39
44
|
# workers
|
|
40
45
|
:prefetch => 10,
|
|
@@ -60,19 +60,24 @@ module Sneakers
|
|
|
60
60
|
Sneakers.logger.debug do
|
|
61
61
|
"#{log_prefix} creating queue=#{retry_name} x-dead-letter-exchange=#{requeue_name}"
|
|
62
62
|
end
|
|
63
|
+
retry_args = retry_queue_arguments.merge(
|
|
64
|
+
:'x-dead-letter-exchange' => requeue_name,
|
|
65
|
+
:'x-message-ttl' => @opts[:retry_timeout] || 60000
|
|
66
|
+
)
|
|
63
67
|
@retry_queue = @channel.queue(retry_name,
|
|
64
68
|
:durable => queue_durable?,
|
|
65
|
-
:arguments =>
|
|
66
|
-
:'x-dead-letter-exchange' => requeue_name,
|
|
67
|
-
:'x-message-ttl' => @opts[:retry_timeout] || 60000
|
|
68
|
-
})
|
|
69
|
+
:arguments => retry_args)
|
|
69
70
|
@retry_queue.bind(@retry_exchange, :routing_key => '#')
|
|
70
71
|
|
|
71
72
|
Sneakers.logger.debug do
|
|
72
73
|
"#{log_prefix} creating queue=#{error_name}"
|
|
73
74
|
end
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
error_args = retry_queue_arguments
|
|
76
|
+
if error_args.empty?
|
|
77
|
+
@error_queue = @channel.queue(error_name, :durable => queue_durable?)
|
|
78
|
+
else
|
|
79
|
+
@error_queue = @channel.queue(error_name, :durable => queue_durable?, :arguments => error_args)
|
|
80
|
+
end
|
|
76
81
|
@error_queue.bind(@error_exchange, :routing_key => '#')
|
|
77
82
|
|
|
78
83
|
# Finally, bind the worker queue to our requeue exchange
|
|
@@ -218,6 +223,17 @@ module Sneakers
|
|
|
218
223
|
def exchange_durable?
|
|
219
224
|
queue_durable?
|
|
220
225
|
end
|
|
226
|
+
|
|
227
|
+
def retry_queue_arguments
|
|
228
|
+
if @opts[:retry_queue_arguments]
|
|
229
|
+
@opts[:retry_queue_arguments].transform_keys(&:to_sym)
|
|
230
|
+
elsif (queue_type = @opts.dig(:queue_options, :arguments, :'x-queue-type') ||
|
|
231
|
+
@opts.dig(:queue_options, :arguments, 'x-queue-type'))
|
|
232
|
+
{ :'x-queue-type' => queue_type }
|
|
233
|
+
else
|
|
234
|
+
{}
|
|
235
|
+
end
|
|
236
|
+
end
|
|
221
237
|
end
|
|
222
238
|
end
|
|
223
239
|
end
|
data/lib/sneakers/version.rb
CHANGED
data/lib/sneakers/worker.rb
CHANGED
|
@@ -76,7 +76,7 @@ module Sneakers
|
|
|
76
76
|
end
|
|
77
77
|
res = block_to_call.call(deserialized_msg, delivery_info, metadata, handler)
|
|
78
78
|
end
|
|
79
|
-
rescue SignalException, SystemExit
|
|
79
|
+
rescue SignalException, SystemExit, Bunny::Exception
|
|
80
80
|
# ServerEngine handles these exceptions, so they are not expected to be raised within the worker.
|
|
81
81
|
# Nevertheless, they are listed here to ensure that they are not caught by the rescue block below.
|
|
82
82
|
raise
|
data/lib/sneakers.rb
CHANGED
|
@@ -46,11 +46,11 @@ module Sneakers
|
|
|
46
46
|
@configured = false
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def daemonize!(loglevel=
|
|
49
|
+
def daemonize!(loglevel=nil)
|
|
50
50
|
CONFIG[:log] = 'sneakers.log'
|
|
51
|
+
CONFIG[:log_level] = loglevel || Logger::INFO
|
|
51
52
|
CONFIG[:daemonize] = true
|
|
52
53
|
setup_general_logger!
|
|
53
|
-
logger.level = loglevel
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def rake_worker_classes=(worker_classes)
|
|
@@ -109,7 +109,7 @@ module Sneakers
|
|
|
109
109
|
if [:info, :debug, :error, :warn].all?{ |meth| CONFIG[:log].respond_to?(meth) }
|
|
110
110
|
@logger = CONFIG[:log]
|
|
111
111
|
else
|
|
112
|
-
@logger = ServerEngine::DaemonLogger.new(CONFIG[:log])
|
|
112
|
+
@logger = ServerEngine::DaemonLogger.new(CONFIG[:log], CONFIG.slice(:log_level, :log_rotate_age, :log_rotate_size))
|
|
113
113
|
@logger.formatter = Sneakers::Support::ProductionFormatter
|
|
114
114
|
end
|
|
115
115
|
end
|
|
@@ -124,4 +124,3 @@ module Sneakers
|
|
|
124
124
|
@publisher = Sneakers::Publisher.new
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
|
-
|
|
@@ -466,4 +466,118 @@ describe 'Handlers' do
|
|
|
466
466
|
end
|
|
467
467
|
end
|
|
468
468
|
end
|
|
469
|
+
|
|
470
|
+
describe 'Maxretry queue arguments inheritance' do
|
|
471
|
+
let(:channel) { Object.new }
|
|
472
|
+
let(:queue) { Object.new }
|
|
473
|
+
|
|
474
|
+
before(:each) do
|
|
475
|
+
Sneakers.configure(:daemonize => true, :log => 'sneakers.log')
|
|
476
|
+
Sneakers::Worker.configure_logger(Logger.new('/dev/null'))
|
|
477
|
+
Sneakers::Worker.configure_metrics
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
describe 'with x-queue-type in queue_options' do
|
|
481
|
+
before do
|
|
482
|
+
@opts = {
|
|
483
|
+
:exchange => 'sneakers',
|
|
484
|
+
:queue_options => {
|
|
485
|
+
:durable => 'true',
|
|
486
|
+
:arguments => { :'x-queue-type' => 'quorum' }
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
mock(queue).name { 'downloads' }
|
|
491
|
+
|
|
492
|
+
@retry_exchange = Object.new
|
|
493
|
+
@error_exchange = Object.new
|
|
494
|
+
@requeue_exchange = Object.new
|
|
495
|
+
@retry_queue = Object.new
|
|
496
|
+
@error_queue = Object.new
|
|
497
|
+
|
|
498
|
+
mock(channel).exchange('downloads-retry',
|
|
499
|
+
:type => 'topic',
|
|
500
|
+
:durable => 'true').once { @retry_exchange }
|
|
501
|
+
mock(channel).exchange('downloads-error',
|
|
502
|
+
:type => 'topic',
|
|
503
|
+
:durable => 'true').once { @error_exchange }
|
|
504
|
+
mock(channel).exchange('downloads-retry-requeue',
|
|
505
|
+
:type => 'topic',
|
|
506
|
+
:durable => 'true').once { @requeue_exchange }
|
|
507
|
+
|
|
508
|
+
mock(channel).queue('downloads-retry',
|
|
509
|
+
:durable => 'true',
|
|
510
|
+
:arguments => {
|
|
511
|
+
:'x-dead-letter-exchange' => 'downloads-retry-requeue',
|
|
512
|
+
:'x-message-ttl' => 60000,
|
|
513
|
+
:'x-queue-type' => 'quorum'
|
|
514
|
+
}).once { @retry_queue }
|
|
515
|
+
mock(@retry_queue).bind(@retry_exchange, :routing_key => '#')
|
|
516
|
+
|
|
517
|
+
mock(channel).queue('downloads-error',
|
|
518
|
+
:durable => 'true',
|
|
519
|
+
:arguments => { :'x-queue-type' => 'quorum' }).once { @error_queue }
|
|
520
|
+
mock(@error_queue).bind(@error_exchange, :routing_key => '#')
|
|
521
|
+
|
|
522
|
+
mock(queue).bind(@requeue_exchange, :routing_key => '#')
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
it 'inherits queue type for retry and error queues' do
|
|
526
|
+
handler = Sneakers::Handlers::Maxretry.new(channel, queue, @opts)
|
|
527
|
+
_(handler).wont_be_nil
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
describe 'with explicit retry_queue_arguments override' do
|
|
532
|
+
before do
|
|
533
|
+
@opts = {
|
|
534
|
+
:exchange => 'sneakers',
|
|
535
|
+
:queue_options => {
|
|
536
|
+
:durable => 'true',
|
|
537
|
+
:arguments => { :'x-queue-type' => 'quorum' }
|
|
538
|
+
},
|
|
539
|
+
:retry_queue_arguments => { :'x-queue-type' => 'classic' }
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
mock(queue).name { 'downloads' }
|
|
543
|
+
|
|
544
|
+
@retry_exchange = Object.new
|
|
545
|
+
@error_exchange = Object.new
|
|
546
|
+
@requeue_exchange = Object.new
|
|
547
|
+
@retry_queue = Object.new
|
|
548
|
+
@error_queue = Object.new
|
|
549
|
+
|
|
550
|
+
mock(channel).exchange('downloads-retry',
|
|
551
|
+
:type => 'topic',
|
|
552
|
+
:durable => 'true').once { @retry_exchange }
|
|
553
|
+
mock(channel).exchange('downloads-error',
|
|
554
|
+
:type => 'topic',
|
|
555
|
+
:durable => 'true').once { @error_exchange }
|
|
556
|
+
mock(channel).exchange('downloads-retry-requeue',
|
|
557
|
+
:type => 'topic',
|
|
558
|
+
:durable => 'true').once { @requeue_exchange }
|
|
559
|
+
|
|
560
|
+
mock(channel).queue('downloads-retry',
|
|
561
|
+
:durable => 'true',
|
|
562
|
+
:arguments => {
|
|
563
|
+
:'x-dead-letter-exchange' => 'downloads-retry-requeue',
|
|
564
|
+
:'x-message-ttl' => 60000,
|
|
565
|
+
:'x-queue-type' => 'classic'
|
|
566
|
+
}).once { @retry_queue }
|
|
567
|
+
mock(@retry_queue).bind(@retry_exchange, :routing_key => '#')
|
|
568
|
+
|
|
569
|
+
mock(channel).queue('downloads-error',
|
|
570
|
+
:durable => 'true',
|
|
571
|
+
:arguments => { :'x-queue-type' => 'classic' }).once { @error_queue }
|
|
572
|
+
mock(@error_queue).bind(@error_exchange, :routing_key => '#')
|
|
573
|
+
|
|
574
|
+
mock(queue).bind(@requeue_exchange, :routing_key => '#')
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
it 'uses explicit retry_queue_arguments over inherited' do
|
|
578
|
+
handler = Sneakers::Handlers::Maxretry.new(channel, queue, @opts)
|
|
579
|
+
_(handler).wont_be_nil
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
469
583
|
end
|
|
@@ -218,7 +218,10 @@ describe Sneakers::Worker do
|
|
|
218
218
|
:hooks => {},
|
|
219
219
|
:handler => Sneakers::Handlers::Oneshot,
|
|
220
220
|
:heartbeat => 30,
|
|
221
|
-
:amqp_heartbeat => 30
|
|
221
|
+
:amqp_heartbeat => 30,
|
|
222
|
+
:log_rotate_age => 5,
|
|
223
|
+
:log_rotate_size => 1048576,
|
|
224
|
+
:log_level => "debug"
|
|
222
225
|
)
|
|
223
226
|
end
|
|
224
227
|
|
|
@@ -256,7 +259,10 @@ describe Sneakers::Worker do
|
|
|
256
259
|
:hooks => {},
|
|
257
260
|
:handler => Sneakers::Handlers::Oneshot,
|
|
258
261
|
:heartbeat => 5,
|
|
259
|
-
:amqp_heartbeat => 30
|
|
262
|
+
:amqp_heartbeat => 30,
|
|
263
|
+
:log_rotate_age => 5,
|
|
264
|
+
:log_rotate_size => 1048576,
|
|
265
|
+
:log_level => "debug"
|
|
260
266
|
)
|
|
261
267
|
end
|
|
262
268
|
|
|
@@ -294,7 +300,10 @@ describe Sneakers::Worker do
|
|
|
294
300
|
:hooks => {},
|
|
295
301
|
:handler => Sneakers::Handlers::Oneshot,
|
|
296
302
|
:heartbeat => 30,
|
|
297
|
-
:amqp_heartbeat => 30
|
|
303
|
+
:amqp_heartbeat => 30,
|
|
304
|
+
:log_rotate_age => 5,
|
|
305
|
+
:log_rotate_size => 1048576,
|
|
306
|
+
:log_level => "debug"
|
|
298
307
|
)
|
|
299
308
|
end
|
|
300
309
|
end
|
|
@@ -437,6 +446,14 @@ describe Sneakers::Worker do
|
|
|
437
446
|
w.do_work(header, nil, "msg", handler)
|
|
438
447
|
end
|
|
439
448
|
|
|
449
|
+
it "should not catch bunny exceptions" do
|
|
450
|
+
w = DummyWorker.new(@queue, TestPool.new)
|
|
451
|
+
mock(w).work("msg").once{ raise Bunny::Exception }
|
|
452
|
+
assert_raises(Bunny::Exception) do
|
|
453
|
+
w.do_work(nil, nil, "msg", nil)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
440
457
|
it "should log exceptions from workers" do
|
|
441
458
|
handler = Object.new
|
|
442
459
|
header = Object.new
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kicks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dotan Nahum
|
|
8
8
|
- Michael Klishin
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 1980-01-02 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: '
|
|
33
|
+
version: '3.0'
|
|
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: '
|
|
40
|
+
version: '3.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: concurrent-ruby
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -265,9 +265,12 @@ files:
|
|
|
265
265
|
- ".github/dependabot.yml"
|
|
266
266
|
- ".github/workflows/ci.yml"
|
|
267
267
|
- ".gitignore"
|
|
268
|
+
- AGENTS.md
|
|
269
|
+
- CLAUDE.md
|
|
268
270
|
- ChangeLog.md
|
|
269
271
|
- Dockerfile
|
|
270
272
|
- Dockerfile.slim
|
|
273
|
+
- GEMINI.md
|
|
271
274
|
- Gemfile
|
|
272
275
|
- Guardfile
|
|
273
276
|
- LICENSE.txt
|
|
@@ -349,14 +352,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
349
352
|
requirements:
|
|
350
353
|
- - ">="
|
|
351
354
|
- !ruby/object:Gem::Version
|
|
352
|
-
version: '
|
|
355
|
+
version: '3.1'
|
|
353
356
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
354
357
|
requirements:
|
|
355
358
|
- - ">="
|
|
356
359
|
- !ruby/object:Gem::Version
|
|
357
360
|
version: '0'
|
|
358
361
|
requirements: []
|
|
359
|
-
rubygems_version:
|
|
362
|
+
rubygems_version: 4.0.10
|
|
360
363
|
specification_version: 4
|
|
361
364
|
summary: Fast background processing framework for Ruby and RabbitMQ
|
|
362
365
|
test_files:
|