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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7899bb171d5e5399547c0b02c33753e23bc8cfaec63e614baa84cd473448a45d
4
- data.tar.gz: 3b5b708557aae6c815a2ad23cf86115e5d39ad397cd1e52099ed2e621b26848a
3
+ metadata.gz: c3ecabfdb6983f2a20237a579d28d78cf868ada1979b4cd4b0b697d36b02a260
4
+ data.tar.gz: b8734c3b4a29ee2e2f5d735b0bbf9862391006506372f29b608af46470ec05fe
5
5
  SHA512:
6
- metadata.gz: 57565fbb9e74e4b990f62e482293ff41cdffebb0b75875b4c654a34e4bb6ed037e2cc9305f15c1c6920e789749a484403badbc2f7aad58b811d614b0d2e51080
7
- data.tar.gz: e6516ab5c10e167a1e94b0a80f82b68dbe330be53603d4cc7132104e0827f013c3cc930b1f3fe2ecc5f2f65a6cbf140707ccd3bd709fbae5ae0eae0747e2b8d7
6
+ metadata.gz: 337a21db50e4ff7f8931abdf9eb1ab91a3a3f30d66b242e823e2a62bb93b162260aaab6c1d1b09f239fac46f1f837c2d8d0c9624e21b9500adc64076c20f123d
7
+ data.tar.gz: 342e9a4ba8bed410c80211cac9df5e1558cbae7e03cf774b3c5d559a3daa75096c3748a2242cb09e35f2194aa2086995cd6f0d6e44058def877b7d83ed6163eb
@@ -1,22 +1,51 @@
1
1
  name: CI
2
2
 
3
- on: [push, pull_request]
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-version }}
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-version: [3.0, 3.1, 3.2, 3.3]
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@v4
39
+ - uses: actions/checkout@v7
14
40
 
15
- - name: Install Ruby ${{ matrix.ruby-version }}
41
+ - name: Set up Ruby ${{ matrix.ruby }}
16
42
  uses: ruby/setup-ruby@v1
17
43
  with:
18
- ruby-version: ${{ matrix.ruby-version }}
19
- bundler-cache: true # 'bundle install', cache gems
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.2.0 and 3.3.0 (in development)
3
+ ## Changes Between 3.3.0 and 3.4.0 (Jul 31, 2026)
4
4
 
5
- No (documented) changes yet.
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) to be passed for an externally-initialized
13
- and managed Bunny connection. In this case, it is entirely up to the caller
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.0+
195
- * Kicks 3.1.x branch: Ruby 3.0+
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-2024 Kicks contributors.
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(">= 2.5")
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', '~> 2.19'
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
- @error_queue = @channel.queue(error_name,
75
- :durable => queue_durable?)
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
@@ -1,3 +1,3 @@
1
1
  module Sneakers
2
- VERSION = "3.2.0"
2
+ VERSION = "3.4.0"
3
3
  end
@@ -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=Logger::INFO)
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.2.0
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: 2025-01-26 00:00:00.000000000 Z
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: '2.19'
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: '2.19'
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: '2.5'
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: 3.6.2
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: