Hi Everyone,

I was a bit slammed leading up to the 0.2 release, and I didn't get a
chance to wrap up any of the ack threads, so I thought I'd post a summary
of what I actually ended up doing. Please check out the docs for more
details, but I'll describe briefly the interface changes in C first and
then how I mapped them into python. The following definitions were added to
messenger.h, starting with the pn_tracker_t handle:

typedef int64_t pn_tracker_t;

There is now a unique handle associated with every call to
pn_messenger_put/get. Note that the signatures of pn_messenger_put/get are
entirely unchanged. If you care about tracking the status of the delivery
associated with a given call you can use the newly added
pn_messenger_outgoing_tracker and pn_messenger_incoming_tracker calls to
access the handle associated with the last put/get calls respectively:

pn_tracker_t pn_messenger_outgoing_tracker(pn_messenger_t *messenger);
pn_tracker_t pn_messenger_incoming_tracker(pn_messenger_t *messenger);

There is now also an accept mode (defaulting to auto):

typedef enum {
  PN_ACCEPT_MODE_AUTO,
  PN_ACCEPT_MODE_MANUAL
} pn_accept_mode_t;

pn_accept_mode_t pn_messenger_get_accept_mode(pn_messenger_t *messenger);
int pn_messenger_set_accept_mode(pn_messenger_t *messenger,
pn_accept_mode_t mode);

If the accept mode is manual, then you have to use the following methods to
either accept or reject incoming messages. Note that you can do this either
individually or cumulatively, for example to accept all retrieved messages
you could do this: pn_messenger_accept(m, pn_messenger_incoming_tracker(m),
PN_CUMULATIVE). This is mapped somewhat more conveniently in the python
binding.

#define PN_CUMULATIVE (0x1)
int pn_messenger_accept(pn_messenger_t *messenger, pn_tracker_t tracker,
int flags);
int pn_messenger_reject(pn_messenger_t *messenger, pn_tracker_t tracker,
int flags);

Now to access the status of a given delivery, you can simply pass the
tracker into the new pn_messenger_status call:

pn_status_t pn_messenger_status(pn_messenger_t *messenger, pn_tracker_t
tracker);

typedef enum {
  PN_STATUS_UNKNOWN = 0,
  PN_STATUS_PENDING = 1,
  PN_STATUS_ACCEPTED = 2,
  PN_STATUS_REJECTED = 3
} pn_status_t;

This call works for both incoming and outgoing deliveries and returns the
last known remote status of the delivery associated with the given tracker.
Of course by default nothing is actually tracked, so it won't provide much
useful information until you turn on tracking. This is done by setting the
incoming and outgoing tracking windows via these new calls:

int pn_messenger_get_outgoing_window(pn_messenger_t *messenger);
int pn_messenger_set_outgoing_window(pn_messenger_t *messenger, int window);

int pn_messenger_get_incoming_window(pn_messenger_t *messenger);
int pn_messenger_set_incoming_window(pn_messenger_t *messenger, int window);

Setting the outgoing tracking window to a positive value will cause the
messenger to track the status of that many deliveries *after* calls to
send. Setting the incoming tracking window to a positive value will cause
the messenger to track the status of that many deliveries *after* calls to
accept.

You can use pn_messenger_settle to clear either window without waiting for
deliveries to roll off the end. This has identical signature to
accept/reject except it can work with both incoming and outgoing trackers.

int pn_messenger_settle(pn_messenger_t *messenger, pn_tracker_t tracker,
int flags); // incoming or outgoing

The python bindings for all this simplify it a little bit. The accept_mode,
and incoming/outgoing window map to properties of the messenger. Also,
unlike in C where we need the return value of put/get to carry the error
code, we have exceptions in python, so I simply returned the tracker
directly from put/get rather than having a separate accessor for the most
recent one. And of course accept/reject take no args and operate
cumulatively by default, however you can pass in an individual tracker if
you wish to operate non cumulatively. I've attached a diff that illustrates
the changes to the send.py/recv.py examples to get them to operate reliably.

--Rafael

Reply via email to