Skip to content

Commit

Permalink
add specs + fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tycooon committed Mar 28, 2024
1 parent 6469a4d commit 52971d6
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 30 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog
All notable changes to this project will be documented in this file.

## [1.0.0] - 2024-03-28
### Added
- Add `ExponentialBackoffHandler` for handling errors in messages
- Optional `queue_suffix` config for read queues

## [0.14.0] - 2023-02-27
### Added
- Exception notifier is required
Expand All @@ -19,7 +24,7 @@ All notable changes to this project will be documented in this file.
- `Gemfile.lock` added

### Fixed
- `unless Sneakers.logger` was never executed
- `unless Sneakers.logger` was never executed

## [0.11.0] - 2021-05-05
### Added
Expand Down
5 changes: 4 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
PATH
remote: .
specs:
rabbit_messaging (0.14.0)
rabbit_messaging (0.15.0)
bunny (~> 2.0)
lamian
rails (>= 5.2)
sneakers (~> 2.0)
sneakers_handlers
tainbox

GEM
Expand Down Expand Up @@ -268,6 +269,8 @@ GEM
rake
serverengine (~> 2.0.5)
thor
sneakers_handlers (0.0.6)
sneakers
sorted_set (1.0.3)
rbtree
set (~> 1.0)
Expand Down
48 changes: 27 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,38 +33,42 @@ require "rabbit_messaging"

- `Rabbit.config` provides setters for following options:

* `group_id` (`Symbol`), *required*
- `group_id` (`Symbol`), *required*

Shared identifier which used to select api. As usual, it should be same as default project_id
(I.e. we have project 'support', which runs only one application in production.
So on, it's group_id should be :support)

* `project_id` (`Symbol`), *required*
- `project_id` (`Symbol`), *required*

Personal identifier which used to select exact service.
As usual, it should be same as default project_id with optional stage_id.
(I.e. we have project 'support', in production it's project_id is :support,
but in staging it uses :support1 and :support2 ids for corresponding stages)

- `queue_suffix` (`String`)

* `exception_notifier` (`Proc`)
Optional suffix added to the read queue name. For example, in case of `group_id = "grp"`, `project_id = "prj"` and
`queue_suffix = "sfx"`, Rabbit will read from queue named `"grp.prj.sfx"`.

- `exception_notifier` (`Proc`)
You must provide your own notifier like this to notify about exceptions:

```ruby
config.exception_notifier = proc { |e| MyCoolNotifier.notify!(e) }
```

* `hooks` (`Hash`)
- `hooks` (`Hash`)

:before_fork and :after_fork hooks, used same way as in unicorn / puma / que / etc

* `environment` (one of `:test`, `:development`, `:production`), *default:* `:production`
- `environment` (one of `:test`, `:development`, `:production`), *default:- `:production`

Internal environment of gem.

* `:test` environment stubs publishing and does not suppress errors
* `:development` environment auto-creates queues and uses default exchange
* `:production` environment enables handlers caching and gets maximum strictness
- `:test` environment stubs publishing and does not suppress errors
- `:development` environment auto-creates queues and uses default exchange
- `:production` environment enables handlers caching and gets maximum strictness

By default gem skips publishing in test and development environments.
If you want to change that then manually set `Rabbit.skip_publishing_in` with an array of environments.
Expand All @@ -73,13 +77,13 @@ require "rabbit_messaging"
Rabbit.skip_publishing_in = %i[test]
```

* `receiving_job_class_callable` (`Proc`)
- `receiving_job_class_callable` (`Proc`)

Custom ActiveJob subclass to work with received messages. Receives the following attributes as `kwarg`-arguments:

* `:arguments` - information about message type (`type`), application id (`app_id`), message id (`message_id`);
* `:delivery_info` - information about `exchange`, `routing_key`, etc;
* `:message` - received RabbitMQ message (often in a `string` format);
- `:arguments` - information about message type (`type`), application id (`app_id`), message id (`message_id`);
- `:delivery_info` - information about `exchange`, `routing_key`, etc;
- `:message` - received RabbitMQ message (often in a `string` format);

```ruby
{
Expand All @@ -93,7 +97,7 @@ require "rabbit_messaging"
}
```

* `before_receiving_hooks, after_receiving_hooks` (`Array of Procs`)
- `before_receiving_hooks, after_receiving_hooks` (`Array of Procs`)

Before and after hooks with message processing in the middle. Where `before_receiving_hooks` and `after_receiving_hooks` are empty arrays by default.

Expand All @@ -109,6 +113,7 @@ require "rabbit_messaging"
config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_4 })
```
---
### Client
Expand All @@ -127,16 +132,16 @@ Rabbit.publish(
- This code sends messages via basic_publish with following parameters:
* `routing_key`: `"support"`
* `exchange`: `"group_id.project_id.fanout"` (default is `"group_id.poject_id"`)
* `mandatory`: `true` (same as confirm_select)
- `routing_key`: `"support"`
- `exchange`: `"group_id.project_id.fanout"` (default is `"group_id.poject_id"`)
- `mandatory`: `true` (same as confirm_select)
It is set to raise error if routing failed
* `persistent`: `true`
* `type`: `"ping"`
* `content_type`: `"application/json"` (always)
* `app_id`: `"group_id.project_id"`
- `persistent`: `true`
- `type`: `"ping"`
- `content_type`: `"application/json"` (always)
- `app_id`: `"group_id.project_id"`
- Messages are logged to `/log/rabbit.log`
Expand All @@ -150,6 +155,7 @@ to teardown and setup external connections between daemon restarts, for example
- After the server runs, received messages are handled by `Rabbit::EventHandler` subclasses.
Subclasses are selected by following code:
```ruby
"rabbit/handler/#{group_id}/#{event}".camelize.constantize
```
Expand Down
2 changes: 1 addition & 1 deletion lib/rabbit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Config

attribute :group_id, Symbol
attribute :project_id, Symbol
attribute :queue_suffix, String
attribute :hooks, default: {}
attribute :environment, Symbol, default: :production
attribute :queue_name_conversion
Expand All @@ -26,7 +27,6 @@ class Config
attribute :before_receiving_hooks, default: []
attribute :after_receiving_hooks, default: []
attribute :skip_publishing_in, default: %i[test development]
attribute :queue_suffix, String
attribute :backoff_handler_max_retries, Integer, default: 6

attribute :receive_logger, default: lambda {
Expand Down
13 changes: 8 additions & 5 deletions lib/rabbit/daemon.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "sneakers"
require "sneakers_handlers"
require "lamian"
require "sneakers/runner"

Expand Down Expand Up @@ -39,14 +40,16 @@ def run(logger: Sneakers.logger)
end

def config
Rails.application.config_for("sneakers").symbolize_keys
@config ||= Rails.application.config_for("sneakers").symbolize_keys
end

def connection
bunny_config = config.delete(:bunny_options).to_h.symbolize_keys
bunny_logger = logger.dup
bunny_logger.level = bunny_config[:log_level] || :info
Bunny.new(**bunny_config, logger: bunny_logger)
@connection ||= begin
bunny_config = config.delete(:bunny_options).to_h.symbolize_keys
bunny_logger = logger.dup
bunny_logger.level = bunny_config.delete(:log_level) || :info
Bunny.new(**bunny_config, logger: bunny_logger)
end
end

private
Expand Down
2 changes: 1 addition & 1 deletion lib/rabbit/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Rabbit
VERSION = "0.14.0"
VERSION = "0.15.0"
end
1 change: 1 addition & 0 deletions rabbit_messaging.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency "lamian"
spec.add_runtime_dependency "rails", ">= 5.2"
spec.add_runtime_dependency "sneakers", "~> 2.0"
spec.add_runtime_dependency "sneakers_handlers"
spec.add_runtime_dependency "tainbox"
end
63 changes: 63 additions & 0 deletions spec/units/rabbit/daemon_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

RSpec.describe Rabbit::Daemon do
before do
allow(app_double).to receive(:config_for).with("sneakers").and_return(sneakers_config)
allow(runner_double).to receive(:run)
allow(logger_double).to receive(:dup).and_return(sneaker_logger_double)

allow(Bunny).to receive(:new).and_return(bunny_double)
allow(Rails).to receive(:application).and_return(app_double)
allow(Rails).to receive(:env).and_return("test")

allow(Sneakers::Runner).to receive(:new).and_return(runner_double)
end

let(:app_double) { double(:rails_app) }
let(:worker_double) { double(:receiving_worker) }
let(:runner_double) { double(:sneakers_runner) }
let(:sneaker_logger_double) { double(:sneaker_logger) }
let(:logger_double) { double(:logger) }
let(:bunny_double) { double(:bunny) }

let(:sneakers_config) do
{
foo: 1,
bunny_options: {
bar: 2,
log_level: "warn",
}
}
end

specify do
expect(Sneakers).to receive(:configure).with(
connection: bunny_double,
env: "test",
exchange_type: :direct,
exchange: "test_group_id.test_project_id",
hooks: {},
supervisor: true,
daemonize: false,
exit_on_detach: true,
log: logger_double,
foo: 1,
)

expect(Bunny).to receive(:new).with(logger: sneaker_logger_double, bar: 2)

expect(Rabbit::Receiving::Worker).to receive(:from_queue).with(
"test_group_id.test_project_id",
handler: SneakersHandlers::ExponentialBackoffHandler,
max_retries: 6,
arguments: {
"x-dead-letter-exchange" => "test_group_id.test_project_id.dlx",
"x-dead-letter-routing-key" => "test_group_id.test_project_id.dlx",
},
)

expect(sneaker_logger_double).to receive(:level=).with("warn")
expect(runner_double).to receive(:run)
Rabbit::Daemon.run(logger: logger_double)
end
end

0 comments on commit 52971d6

Please sign in to comment.