Qpid Proton AMQP Library
This is a library for sending and receiving AMQP messages. It can be used to build clients and servers.
Installing
You can install the latest published Gem with
gem install qpid_proton
NOTE: before installing the Gem, you must install the proton-C library.
The proton-C library can be installed by the package manager on many platforms,
e.g. yum install qpid-proton-c # Fedora < 25, RHEL < 7 dnf install
qpid-proton-c # Fedora >= 25, RHEL >= 7
You can also download a source release or the latest development code from qpid.apache.org/proton. To build from source:
cmake -DBUILD_BINDINGS=ruby && make
This produces a Gem file at:
BUILD_DIR/ruby/qpid_proton-VERSION.gem
You can install the gem with gem install
Overview
Qpid::Proton::Message represents a message that can be sent or received. A message body can be a string or byte sequence encoded any way you choose. However, AMQP also provides standard, interoperable encodings for basic data types like Hash and Array. The equivalent AMQP encodings can be understood as maps or sequences in any programming langauge with an AMQP library.
Qpid::Proton::Link allows messages to be transferred to or from a remote AMQP process. The Qpid::Proton::Sender subclass sends messages, the Qpid::Proton::Receiver subclass receives them. Links have a source and target address, as explained below.
Links are grouped in a Qpid::Proton::Session. Messages in the same session are sent sequentially, while those on different sessions can be interleaved. A large message being sent on one session does not block messages being sent on another session.
Sessions belong to a Qpid::Proton::Connection. If you don’t need multiple sessions, a connection will create links directly using a default session.
A Qpid::Proton::Transfer represents the transfer of a message, the Qpid::Proton::Delivery subclass allows a receiver to accept or reject an incoming message. The Qpid::Proton::Tracker subclass allows a sender to track the status of a sent message and find out if it was accepted or rejected.
A transfer is settled when both ends are done with it. Different settlement methods give different levels of reliability: at-most-once, at-least-once, and exactly-once. See below.
Anatomy of a Proton application
Qpid::Proton::Container is the top-level object in a Proton application. A client uses Qpid::Proton::Container#connect to establish connections. A server uses Qpid::Proton::Container#listen to accept connections.
Proton is an event-driven library. You implement one or more handlers which subclass MessagingHandler and override functions to handle AMQP events, such as #on_message. Each connection is associated with a handler for its events. Qpid::Proton::Container#run polls all connections and listeners and calls the event handling functions on your handlers.
A multi-threaded application can call Qpid::Proton::Container#run in more than one thread, the container will use all the #run threads as a thread pool to dispatch events.
Sources and targets
Every link has two addresses, source and target. The most common pattern for using these addresses is as follows:
When a client creates a Receiver link, it sets the source address. This means “I want to receive messages from this source”. This is often referred to as “subscribing” to the source. When a client creates a Sender link, it sets the target address. This means “I want to send to this target”.
In the case of a broker, the source or target usually refers to a queue or topic. In general they can refer to any AMQP-capable node.
In the request-response pattern, a request message carries a reply-to address for the response message. This can be any AMQP address, but it is often useful to create a temporary address for the response message. The client creates a receiver with no source address and the dynamic flag set. The server generates a unique source address for the receiver, which is discarded when the link closes. The client uses this source address as the reply-to when it sends the request, so the response is delivered to the client’s receiver.
The server_direct.cpp example shows how to implement a request-response server.
Settling a Message Transfer
A message transfer is settled at one end of a link when that end of the link has finished with the message and forgotten it.
Pre-settled messages are settled by the sender before sending. This gives _at most once_ reliability(also known as _best effort_, unreliable or _fire and forget_) since the sender never knows for sure if the message arrived. If the connection is lost before the message is received by the receiver, the message will not be delivered.
If the sender does not pre-settle a message, then the receiver settles it once it has been processed. The sender is informed of the settlement via the Tracker. If the connection is lost before the sender has received notice of settlement, the delivery is considered in-doubt and the sender can re-send it. This ensures it eventually gets delivered (provided the connection and link can be reestablished) but it is possible for multiple copies of the same message are delivered, so the receiver must be aware of that. This is known as at_least_once reliability.
Multi-threaded applications
Qpid::Proton::Container#run can be called by multiple threads concurrently, giving the container a thread-pool to execute handler methods in parallel.
Instances of Qpid::Proton::Connection and objects associated with it (Qpid::Proton::Session, Qpid::Proton::Sender, Qpid::Proton::Receiver, Qpid::Proton::Delivery, Qpid::Proton::Tracker) are not thread-safe and must be used correctly when multiple threads call Qpid::Proton::Container#run
Calls to Qpid::Proton::MessagingHandler and Qpid::Proton::Listener::Handler methods by the Qpid::Proton::Container are automatically serialized for each connection instance.
Other threads may have code similarly serialized by adding it to the Qpid::Proton::Connection#work_queue for the connection. Each object related to a Qpid::Proton::Connection also provides a work_queue
method.
You also need to use the Qpid::Proton::WorkQueue to communicate between a Qpid::Proton::MessagingHandler method call for one connection instance, and a different Qpid::Proton::Connection instance in the same container, as separate connections can be processed in parallel.