0.01
Low commit activity in last 3 years
A long-lived project that still receives updates
Rabbit (Rabbit Messaging)
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 3
~> 2.0
>= 0
>= 6.1
 Project Readme

Rabbit (Rabbit Messaging) ยท Gem Version Coverage Status

Provides client and server support for RabbitMQ

Installation

gem "rabbit_messaging"
$ bundle install
# --- or ---
$ gem install "rabbit_messaging"
require "rabbit_messaging"

Usage

  • Configuration
  • Client
  • Server

Configuration

  • RabbitMQ connection configuration fetched from the bunny_options section of /config/sneakers.yml

  • Rabbit.config provides setters for following options:

    • 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

      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)

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

        config.exception_notifier = proc { |e| MyCoolNotifier.notify!(e) }
    • 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

      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

      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.

       Rabbit.skip_publishing_in = %i[test]
    • 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);
      {
        message: '{"hello":"world","foo":"bar"}',
        delivery_info: { exchange: "some exchange", routing_key: "some_key" },
        arguments: {
          type: "some_successful_event",
          app_id: "some_group.some_app",
          message_id: "uuid",
        }
      }
    • 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.

      It's advised to NOT place procs with long execution time inside.

      Setup:

        config.before_receiving_hooks.append(proc { |message, arguments| do_stuff_1 })
        config.before_receiving_hooks.append(proc { |message, arguments| do_stuff_2 })
      
        config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_3 })
        config.after_receiving_hooks.append(proc { |message, arguments| do_stuff_4 })

Client

Rabbit.publish(
  routing_key: :support,
  event: :ping,
  data: { foo: :bar }, # default is {}
  exchange_name: 'fanout', # default is fine too
  confirm_select: true, # setting this to false grants you great speed up and absolutelly no guarantees
  headers: { "foo" => "bar" }, # custom arguments for routing, default is {}
  message_id: "asdadsadsad", # A unique identifier such as a UUID that your application can use to identify the message.
)
  • 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)

      It is set to raise error if routing failed

    • persistent: true

    • type: "ping"

    • content_type: "application/json" (always)

    • app_id: "group_id.project_id"

  • Messages are logged to /log/rabbit.log


Server

  • Server is supposed to run inside a daemon via the daemons-rails gem. Server is run with Rabbit::Daemon.run. before_fork and after_fork procs in Rabbit.config are used to teardown and setup external connections between daemon restarts, for example ORM connections

  • After the server runs, received messages are handled by Rabbit::EventHandler subclasses in two possible ways:

    • a) Subclasses are selected by following code(by default):
      rabbit/handler/#{group_id}/#{event}".camelize.constantize
    • b) you can change default behaviour to your own logic by setting the handler_resolver_callable config option with a Proc that should return the handler class:
      Rabbit.config.handler_resolver_callable = -> (group_id, event) { "recivers/#{group_id}/#{event}".camelize.constantize }

    They use powerful Tainbox api to handle message data. Project_id also passed to them.

    If you wish so, you can override initialize(message), where message is an object with simple api (@see lib/rabbit/receiving/message.rb)

    Handlers can specify a queue their messages will be put in via a queue_as class macro (accepts a string / symbol / block with |message, arguments| params)

  • Received messages are logged to /log/sneakers.log, malformed messages are logged to /log/malformed_messages.log and deleted from queue


Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/umbrellio/rabbit_messaging.

License

Released under MIT License

Authors

Team Umbrellio


Supported by Umbrellio