Skip to content

Releases: cloudamqp/amqp-client.rb

Release 2.1.0

Choose a tag to compare

@github-actions github-actions released this 23 Jun 15:16
v2.1.0
  • Changed: Dropped support for Ruby 3.2 (now requires Ruby >= 3.3).
  • Fixed: A malformed frame end during the connection handshake (e.g. connecting to a non-AMQP service) now raises the intended Error::UnexpectedFrameEnd instead of a NameError from a mistyped constant, which previously surfaced as a confusing invalid handshake (uninitialized constant AMQP::Client::Error::UnexpectedFrameTypeEnd) message
  • Fixed: The handshake now buffers the full 7-byte frame header before parsing it. On JRuby the header could arrive split across reads, leaving frame_size nil and raising NoMethodError ("undefined method '+' for nil") instead of UnexpectedFrameEnd when connecting to a non-AMQP service
  • Fixed: Channel#wait_for_confirms no longer hangs when the broker closes the channel (e.g. a publish to a missing exchange) right before the publishing thread starts waiting. The closed-channel check now runs before the condition-variable wait, so the wakeup from #closed! can't be lost. This resolves a flaky ChannelClosed-expected timeout that surfaced on truffleruby, whose threads run truly in parallel.
  • Fixed: When the read loop exits on an abrupt socket close (no channel/connection close frame from the broker), open channels are now marked closed, so callers blocked in #wait_for_confirms or awaiting a broker reply raise ConnectionClosed instead of hanging forever.
  • Fixed: An ack/nack for a delivery tag the channel isn't tracking (a duplicate, out-of-order, or broker quirk) is now ignored instead of raising. The previous bare RuntimeError ran on the read loop thread, tearing down the connection β€” and, under the high-level supervisor, aborting the whole process.
  • Fixed: Consumer#cancel now closes the dedicated channel opened by subscribe, preventing a channel leak on long-lived connections that subscribe/cancel repeatedly (#81)
  • Fixed: Consumer threads no longer crash with ConnectionClosed/ChannelClosed when the connection or channel closes while a delivery is being processed (e.g. an ack/reject/publish racing a shutdown); the consumer now stops quietly. Previously surfaced as a flaky error on JRuby/TruffleRuby, whose threads run truly in parallel.
  • Added: logger: option on AMQP::Client.new that emits info/warn lifecycle messages for connect, reconnect, and disconnect in the supervised #start loop. The prefix uses ?name= from the URL when present.
  • Added: Every thread the library spawns (read_loop, heartbeat, consumer workers, on_return, supervisor, reconnect_setup) now gets a descriptive Thread#name. When the URL includes ?name=, that identifier is embedded in each thread's name too, matching the lifecycle log prefix.

Release 2.0.1

Choose a tag to compare

@github-actions github-actions released this 18 Nov 08:28
572694f
  • Fixed: Ensure closing channels on basic get high level api (#73)
  • Improved: Clean up migration guide
  • Added: GitHub release notes for v2.0.0

Release 2.0.0

Choose a tag to compare

@github-actions github-actions released this 27 Oct 14:48

We're excited to announce the release of AMQP Client 2.0! This major version brings significant improvements to API clarity, consistency, and functionality while introducing powerful new features for automatic message encoding and configuration management.

🎯 Highlights

  • Keyword Arguments Throughout - All public methods now use keyword arguments for improved clarity and safety
  • Unified Configuration API - New AMQP::Client.configure block for centralized configuration
  • Automatic Message Encoding - Built-in support for JSON, gzip, and deflate with extensible codec registry
  • RPC Support - Native RPC client/server implementation
  • Enhanced Consumer Control - Subscribe methods now return cancelable Consumer objects
  • Automatic Ack/Reject - Queue#subscribe handles acknowledgments automatically

πŸ’” Breaking Changes

1. Keyword Arguments (All APIs)

All public methods now require keyword arguments instead of positional arguments:

# v1.x
amqp.publish("message", "amq.topic", "routing.key")

# v2.0
amqp.publish("message", exchange: "amq.topic", routing_key: "routing.key")

Migration: Update all method calls to use keyword arguments. See the Migration Guide for complete examples.

2. Exchange Convenience Methods Renamed

Exchange type methods now have an _exchange suffix for clarity:

# v1.x
amqp.direct()
amqp.topic()
amqp.fanout()

# v2.0
amqp.direct_exchange()
amqp.topic_exchange()
amqp.fanout_exchange()

3. Direct Exchange Default Name

The default direct exchange name changed from "" to "amq.direct" for consistency:

# v1.x
amqp.direct()  # Returns exchange with name ""

# v2.0
amqp.direct_exchange()     # Returns "amq.direct"
amqp.direct_exchange("")   # Explicitly use empty string if needed

4. Subscribe Returns Consumer

Client#subscribe and Queue#subscribe now return a Consumer object that can be cancelled:

consumer = queue.subscribe(prefetch: 10) do |msg|
  # Process message
end

# Later...
consumer.cancel

5. Other Breaking Changes

  • Channel#basic_subscribe now returns Connection::Channel::ConsumeOk
  • Connection::Channel::QueueOk is now an immutable Data class instead of Struct

✨ New Features

Unified Configuration

Configure all settings in one place with the new configure block:

AMQP::Client.configure do |config|
  config.enable_builtin_codecs  # JSON, gzip, deflate
  config.default_content_type = "application/json"
  config.default_content_encoding = "gzip"
  config.strict_coding = true

  # Register custom codecs
  config.register_parser(content_type: "application/msgpack", parser: MsgPackParser)
end

Automatic Message Encoding

Built-in support for JSON serialization and compression:

# Enable built-in codecs
AMQP::Client.configure do |config|
  config.enable_builtin_codecs
end

# Automatically serializes to JSON
queue.publish({ user: "john", action: "login" }, content_type: "application/json")

# Automatically deserializes
queue.subscribe do |msg|
  data = msg.parse  # Returns Ruby hash
end

Supported formats:

  • application/json - JSON encoding/decoding
  • gzip - Gzip compression
  • deflate - Deflate compression

Automatic Ack/Reject

Queue#subscribe now handles message acknowledgments automatically:

queue.subscribe(prefetch: 20) do |msg|
  process(msg)
  # Automatically ack'd on success
  # Automatically rejected (with requeue) on exception
end

Manual control is still available if needed.

RPC Support

Native RPC implementation for request-response patterns:

# Server
amqp.rpc_server("rpc_queue") do |request|
  { result: request[:value] * 2 }
end

# Client
rpc = amqp.rpc_client
response = rpc.call({ value: 21 }, routing_key: "rpc_queue")
# => { result: 42 }

Queue Polling

Poll messages without subscribing:

msg = queue.get
if msg
  process(msg)
  msg.ack
end

Enhanced Queue Options

  • passive - Check queue existence without creating
  • exclusive - Delete queue when connection closes

Improved Consumer Management

  • Client#started? - Check if client is started
  • Message#delivery_info - Structured access to delivery metadata
  • Consumer objects can be cancelled

πŸ”§ Additional Improvements

  • Thread Safety - Client#start is now thread-safe
  • Confirm Handling - wait_for_confirms properly handles NACKs and returns boolean
  • Network Optimization - Nagle's algorithm disabled for lower latency
  • Bug Fixes - Various fixes including minitest compatibility

πŸ“š Migration

Please review the complete Migration Guide for detailed migration instructions, code examples, and a step-by-step checklist.

Quick Migration Checklist

  1. βœ… Update all method calls to use keyword arguments
  2. βœ… Rename direct(), fanout(), topic(), headers() to *_exchange()
  3. βœ… Replace require "amqp-client/enable_builtin_codecs" with configure block
  4. βœ… Store returned Consumer objects if you need to cancel subscriptions
  5. βœ… Review direct exchange usage if relying on empty string default
  6. βœ… Update any code mutating QueueOk structures

Migration Support

πŸ™ Acknowledgments

Thank you to everyone who contributed feedback, bug reports, and suggestions that shaped this release!


Full Changelog: v1.2.1...v2.0.0

Release 1.2.1

Choose a tag to compare

@github-actions github-actions released this 15 Sep 12:40
  • Added: Convenience methods for creating exchange types: fanout(), direct(), topic(), and headers()
  • Added: Support for binding with high level objects (Exchange and Queue objects can now be passed as binding sources)
  • Fixed: Bug where a client without any connection could not be closed properly

v1.2.0

Choose a tag to compare

@baelter baelter released this 12 Sep 11:51

What's Changed

Full Changelog: v1.1.7...v1.2.0