quickfixj
quickfixj copied to clipboard
Proposal: add DoNotFulfillResendRequest exception to allow applications to prevent resend
Adds exception DoNotFulfillResendRequest to fromAdmin, in the spirit of RejectLogon, to alter the behavior of the engine.
Applications can throw this exception to abort the fulfillment of an incoming ResendRequest.
The example use case for this comes from real life, in production at one of the largest derivatives exchanges:
- the counterparty sends an excessive number of large ResendRequests in error (multiple per second)
- this causes a massive spike in cpu, disk, and memory utilization
- there is no way to prevent quickfix from fulfilling the request, other than to log out / disconnect the counterparty
- even if logged out, they will reconnect and repeat the same behavior, causing the same problem with resources
- blocking the counterparty from reconnecting is undersirable: it puts the operational burden on the counterparty experiencing the problem, instead of on the counterparty causing the problem
- the ability to prevent the fulfillment of the ResendRequest allows for keeping the session alive and using it to report the problem via Session-level Reject messages
- if the offending counterparty is able to correct the problem, the session can continue, including resend, without operational intervention by the counterparty on the receiving end of the problem
- this new exception can work in conjunction with existing throttling logic that is in place for other message flow
I know this is a slightly unusual use case, but it's a real one, at a very large institution. This was the best solution we could think of -- if there's a better way to go about it, we'd love to hear your feedback. Thanks!
Hi @mgatny , thanks for the PR. Sounds like a sensible enhancement. At first sight, without digging deeper into the code, the following approach might also work:
Set RejectMessageOnUnhandledException=Y and throw an unhandled exception (e.g. RuntimeException) out of your callback if you receive a ResendRequest. That should also send a session-level reject and increment the target seqnum.
https://github.com/quickfix-j/quickfixj/blob/e612ee6858673e6d4e1e21999fbda105e9c283bc/quickfixj-core/src/main/java/quickfix/Session.java#L1201-L1227
One question: are redundant resend requests not ignored? They actually should. Or are the requests all for a different range of seqnums?
P.S.: Also see #639
RejectMessageOnUnhandledException=Y is interesting, I didn't know there was such a thing. Maybe instead of a new exception, we could modify that logic slightly so that a reject reason is given (currently it looks like it will give a reason of OTHER with a blank Text field). One (potential) advantage of the new exception is that it lets the Application decide what the behavior should be (e.g. send a Reject, send one of the newer throttling-related messages, etc) but maybe that isn't useful enough to warrant a whole new exception.
Re: redundant resend requests: as far as I know, qf/j does a proper job of not sending them (unless configured to do so), but it fulfills every resend request it receives, even if redundant.
I've added RejectMessageOnUnhandledException a couple of years ago since there sometimes were unhandled exceptions, the seqnum was not incremented and one was in an endless loop because the same problematic message was redelivered over and over.
But yes, it would be beneficial to be able to pass a custom text and/or reason. Shall I open an issue for it?
Redundant resend requests: you are right, I mixed that one up. Another question: the ResendRequests in your initial problem were all for different ranges I suppose? Because otherwise I think one could check if the range for the resend is already being resent and abort the resend processing.
Hi @mgatny
is RejectMessageOnUnhandledException good enough for your use case?
Thanks,
Chris
Hi Chris, still waiting on additional feedback from the client, but for now RejectMessageOnUnhandledException is working for them.
Hi @chrjohn I think #851 will resolve the issue, let me know if you think it needs anything else.
Superseded by #851