kanin

Build Status][travis badge]][travis]
[![LFE Versions][lfe badge]][lfe]
[![Erlang Versions][erlang badge]][versions]
[![Tags][github tags badge] [ Downloads

An LFE Wrapper for the Erlang RabbitMQ (AMQP) Client

Table of Contents

Introduction

The kanin library is a wrapper for various modules in the Erlang AMQP client library. kanin was created in order to not only provide a less verbose AMQP client library for LFE hackers, but one that was also more Lispy.

Installation

To pull in kanin as part of your project, just add it to your rebar.config deps:

  {deps, [
    ...
    {kanin, {git, "git@github.com:lfex/kanin.git", {branch, "master"}}}
  ]}.

And then do:

    $ rebar3 compile

Documentation

Below, in the “Usage” section, you will find information about using Kanin with RabbitMQ in LFE projects.

Also, you may be interested in the Kanin tutorials, which have been translated into LFE from the official RabbitMQ docs for Python and Erlang.

Supported Modules

The following amqp_* modules have been included in kanin:

If your favorite amqp_* module is not among those, feel free to submit a new ticket requesting the addition of your desired module(s) or submit a pull request with the desired inclusion added.

Usage

Copyright Notice

The following content was copied from the Erlang Client User Guide on the RabbitMQ site. The original copyright was in 2014, held by Pivotal Software, Inc.

The LFE AMQP Client Library

The AMQP client provides an Erlang interface to compliant AMQP brokers. The client follows the AMQP execution model and implements the wire level marshaling required to encode and decode AMQP commands in a protocol conformant fashion. AMQP is a connection orientated protocol and multiplexes parallel interactions via multiple channels within a connection.

This user guide assumes that the reader is familiar with basic concepts of AMQP and understands exchanges, queues and bindings. This information is contained in the protocol documentation on the AMQP website. For details and exact definitions, please see the AMQP specification document.

The basic usage of the client follows these broad steps:

Programming Model

Once a connection has been established, and a channel has been opened, an LFE application will typically use the kanin-chan:call/{2,3} and kanin-chan:cast/{2,3} functions to achieve most of the things it needs to do.

The underlying Erlang AMQP client library is made up of two layers:

There are two drivers in the client library:

At run-time, the Erlang client library re-uses a subset of the functionality from the RabbitMQ broker. In order to keep the a client deployment independent of RabbitMQ, the Erlang client build process produces an archive containing all of the common modules. This archive is then put onto the load path of the client application.

For more detailed information on the API, please refer to the reference documentation.

Furthermore, the test suite that is part of the source distribution of the client library contains many complete examples of how to program against the API.

AMQP Commands

The general mechanism of interacting with the broker is to send and receive AMQP commands that are defined in the protocol documentation. During build process, the machine-readable version of the AMQP specification is used to auto-generate Erlang records for each command. The code generation process also defines sensible default values for each command. Using default values allows the programmer to write terser code - it is only necessary to override a field if you require non-default behaviour. The definition of each command can be consulted in the include/rabbit-framing.lfe header file. For example, when using the (make-exchange.declare ...) record-creating macro, specifying the following:

(make-exchange.declare exchange (list_to_binary "my_exchange"))

is equivalent to this:

(make-exchange.declare
  exchange #"my_exchange"
  ticket 0
  type #"direct"
  passive 'false
  durable 'false
  auto_delete 'false
  internal 'false
  nowait 'false
  arguments '())

Including Header Files

The LFE client uses a number of record definitions which you will encounter in this guide. These records fall into two broad categories:

To gain access to these records, you need to include the amqp-client.lfe file in every module that uses the Erlang client:

(include-lib "kanin/include/amqp-client.lfe")

Connecting to a Broker

The kanin-conn module is used to start a connection to the broker. It requires either a direction connection options record or a network connection options record. These may be generated either by creating the records directly or providing connection information in a URI and having those parsed to generate the record for you.

Example record-creation:

lfe> (make-amqp_params_direct)
#(amqp_params_direct none none #"/" nonode@nohost none ())

and

lfe> (make-amqp_params_network host "localhost")
#(amqp_params_network
  #"guest"
  #"guest"
  #"/"
  "localhost"
  undefined 0 0 0 infinity none
  (#Fun<amqp_auth_mechanisms.plain.3> #Fun<amqp_auth_mechanisms.amqplain.3>)
  () ())

Example option URI parsing:

lfe> (kanin-uri:parse "amqp://dave:secret@")
#(ok #(amqp_params_direct #"dave" #"secret" #"/" nonode@nohost none ()))

and

lfe> (kanin-uri:parse "amqp://alice:secret@host:10000/vhost")
#(ok
  #(amqp_params_network
    #"alice"
    #"secret"
    #"vhost"
    "host"
    10000 0 0 10 infinity none
    (#Fun<amqp_uri.11.121287672> #Fun<amqp_uri.11.121287672>)
    () ()))

(For more information in this, see the section below: “Connecting To A Broker with AMQP URIs”.)

To use these options to create an actual connection, use the kanin-conn module:

lfe> (set `#(ok ,net-opts) (kanin-uri:parse "amqp://localhost"))
lfe> (set `#(ok ,conn) (kanin-conn:start net-opts))

That’s in the REPL; in an application using kanin, you’d want to use something like a (let ...) statement.

The ksnin-conn:start function returns #(ok ,conn), where conn is the pid of a process that maintains a permanent connection to the broker.

In case of an error, the above call returns #(error ,error).

The example above has just "localhost" as a parameter. However, there will often be many more than that.

An AMQP broker contains objects organised into groups called virtual hosts. The concept of virtual hosts gives an administrator the facility to partition a broker resource into separate domains and restrict access to the objects contained within these groups. AMQP connections require client authentication and the authorisation to access specific virtual hosts.

The (make-amqp_params_network) record macro sets the following default values:

Parameter Default Value
username guest
password guest
virtual_host /
host localhost
post 5672
channel_max 0
frame_max 0
heartbeat 0
ssl_options none
auth_mechanisms (list #'amqp_auth_mechanisms:plain/3 #'amqp_auth_mechanisms:amqplain/3)
client_properties '()

These values are only the defaults that will work with an out of the box broker running on the same host. If the broker or the environment has been configured differently, these values can be overridden to match the actual deployment scenario.

SSL options can also be specified globally using the ssl_options environment key for the amqp-client application. They will be merged with the SSL parameters from the URI (the latter will take precedence).

If a client wishes to run inside the same Erlang cluster as the RabbitMQ broker, it can start a direct connection that optimises away the AMQP codec. To start a direct connection, use kanin-conn:start/1 with the parameter set to an (make-amqp_params_direct) record.

Providing a username and password is optional, since the direct client is considered trusted anyway. If a username and password are provided then they will be checked and made available to authentication backends. If a username is supplied, but no password, then the user is considered trusted and logged in unconditionally. If neither username nor password are provided then the connection will be considered to be from a “dummy” user which can connect to any virtual host and issue any AMQP command.

The (make-amqp_params_direct) record macro sets the following default values:

Parameter Default Value
username #"guest"
password #"guest"
virtual_host #"/"
node (node)
client_properties '()

Connecting To A Broker with AMQP URIs

Instead of working the (make-amqp_params_*) records directly, AMQP URIs may be used. The (kanin-uri:parse/1) function is provided for this purpose. It parses an URI and returns the equivalent amqp_params_* record. Diverging from the spec, if the hostname is omitted, the connection is assumed to be direct and an amqp_params_direct record is returned. In addition to the standard host, port, user, password and vhost parameters, extra parameters may be specified via the query string (e.g. "?heartbeat=5").

AMQP URIs are defined with the following ABNF rules:

amqp_URI       = "amqp://" amqp_authority [ "/" vhost ] [ "?" query ]
amqp_authority = [ amqp_userinfo "@" ] host [ ":" port ]
amqp_userinfo  = username [ ":" password ]
username       = *( unreserved / pct-encoded / sub-delims )
password       = *( unreserved / pct-encoded / sub-delims )
vhost          = segment

Here are some examples:

Parameter Username Password Host Port Vhost
amqp://alice:secret@host:10000/vhost “alice” “secret” “host” 10000 “vhost”
amqp://bo%62:%73ecret@h%6fst:10000/%76host “bob” “secret” “host” 10000 “vhost”
amqp://
amqp://:@/ “” “” “”
amqp://carol@ “carol”
amqp://dave:secret@ “dave” “secret”
amqp://host “host”
amqp://:10000 10000
amqp:///vhost “vhost”
amqp://host/ “host” “”
amqp://host/%2f “host” “/“
amqp://[::1] “[::1]”

Using a connection URI, you can creat either direct or network connection options, and then use those to connect via the kanin-conn:start function (as demonstrated above).

Creating Channels

TBD

Managing Exchanges and Queues

TBD

Sending Messages

TBD

Receiving Messages

TBD

Subscribing to Queues

TBD

Subscribing Internals

TBD

Closing Channels and the Connection

TBD

Complete Example

TBD

Client Deployment

TBD

Egress Flow Control

TBD

Ingress Flow Control

TBD

Handling Returned Messages

TBD

License

Apache License, Version 2.0

Copyright © 2014-2017, BilloSystems, Ltd. Co.

Copyright © 2015-2017, Ricardo Lanziano

Copyright © 2015-2017, Duncan McGreggor