An interesting lesson I learned building these brokers, this is more
about the Go language than the differences between the proton and
Go channels encourages proper flow control: they cannot be unbounded
and sending to a full channel blocks until a value is removed.
Both Go brokers use fixed-size bounded channels as simple queues, and
as receive buffers for receiving links (in the electron API the channel
is hidden by the Receiver interface but it is there.) Both use
goroutines to transfer messages from buffer to queue.
When a queue is full, goroutines sending to it are blocked. Receivers
can buffer messages but only up to a fixed limit, at which point they
stop issuing credit. So once the queues are full, clients sending
messages are also blocked, the broker will not grow without limit. As
soon as a message is taken off a queue, one of the receiver goroutines
can unblock, move a message from buffer to queue, and issue credit to
get the whole thing moving again.
Complete end-to-end flow control across the queue (which was a big
effort to implement in qpidd c++ for example) falls out in a trivial
broker demo as a natural consequence of using channels and goroutines.
On Thu, 2015-10-22 at 18:19 -0400, aconway wrote:
> The Go binding for proton provides 2 alternate APIs, `proton` is an
> exact analogue of the event-driven proton C API and `electron` which
> a more go-oriented, procedural API. The differences were motivated by
> the concurrency features of the Go language but there may be lessons
> learn for other languages. Take a look at
> ## A tale of two brokers
> The `proton` and `electron` packages provide two alternate APIs for
> AMQP applications. See [the proton Go README](
> -c/bindings/go/src/qpid.apache.org/README.md) for a discussion of why
> there are two APIs.
> The examples `proton/broker.go` and `electron/broker.go` both
> the same simple broker-like functionality using each of the two APIs.
> They both handle multiple connections concurrently and store messages
> on bounded queues implemented by Go channels.
> However the `electron/broker` is less than half as long as the
> `proton/broker` illustrating why it is better suited for most Go
> `proton/broker` must explicitly handle proton events, which are
> processed in a single goroutine per connection since proton is not
> concurrent safe. Each connection uses channels to exchange messages
> between the event-handling goroutine and the shared queues that are
> accessible to all connections. Sending messages is particularly
> since we must monitor the queue for available messages and the
> link for available credit in order to send messages.
> `electron/broker` takes advantage of the `electron` package, which
> hides all the event handling and passing of messages between
> beind behind straightforward interfaces for sending and receiving
> messages. The electron broker can implement links as simple
> that loop popping messages from a queue and sending them or receiving
> messages and pushing them to a queue.