Suppose I am publishing guaranteed messages to a topic. I want to avoid sending duplicate messages. I am also going to send messages in transactional batches to make it easier to guarantee the broker receives the messages in the same order that the publisher creates them, without having to fall back to completely sequential Send-and-Wait-per-message logic.
OK, I Send()
a message via an ITransactedSession
, with a SOLCLIENT_OK
result. For the sake of simplicity I will assume there a single message in the transaction batch for this example.
I then call Commit()
.
If this also returns SOLCLIENT_OK
we’re good, move onto the next message (batch).
My confusion lies in trying to understand how to handle the alternative Commit result possibilities. There is not much documentation on use of transactions, and none, as far as I can find, specific to the .net API.
Possibility 1: I get an OperationErrorException with a ReturnCode of SOLCLIENT_ROLLBACK
I then call GetLastSDKErrorInfo and determine that the subcode is SpoolOverQuota . This is, I believe, an error that could be overcome with a simple wait-and-retry for the Send and Commit unit.
Is that the appropriate action for SpoolOverQuota, and SpoolOverQuota the only subcode where wait-and-retry is the appropriate action? This seems to be sort of equivalent to the case where a regular ISession.Send
results in a “NACK” callback due to a queue being full, and therefore has the same retry resolution.
Everything else under SOLCLIENT_ROLLBACK seems to imply a need to reset or recreate some other state. I think in all of those cases I would simply restart the whole publisher, since trying to appropriately handle all of the other subcodes individually doesn’t seem worth the trouble. (1)
Possibility 2: I get an OperationErrorException with a ReturnCode of SOLCLIENT_FAIL
What now? The documentation describes this situation thus:
“the commit may have succeeded on the message-router before the response was lost. Or the commit request may have failed (roll back).”
I take this to mean that the transaction has in fact been either committed or rolled back, and we don’t know which. In other words, it does not mean that neither has happened, and thus it would be pointless to immediately retry the Commit. Is that right? And is there any way to tell, from a subsequent operation, which it was? In other words, after this occurs, is there any subsequent code I can write to determine whether it was actually a rollback and I should redo the Send and Commit unit, or it was a commit and I should move on to the next message?
(1) In my existing solution restarting the publisher would not result in data loss - the message would be picked up from the outbox and re-sent.