Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QRest SendResponse participant does not send response in the prepare method #300

Open
mchhil-incomm opened this issue Mar 11, 2024 · 2 comments

Comments

@mchhil-incomm
Copy link

https://github.com/jpos/jPOS-EE/blob/master/modules/qrest/src/main/java/org/jpos/qrest/SendResponse.java#L49-L50

I have a participant that takes a lot of time. LongRunningParticpant

This LongRunningParticpant is placed after the SendResponse participant in the txn mgr.

But since the response is only sent in the commit method

https://github.com/jpos/jPOS-EE/blob/master/modules/qrest/src/main/java/org/jpos/qrest/SendResponse.java#L54-L60

It gets sent after the  'LongRunningParticpant' completes.

Snippet of profiler

    <profiler>
     prepare: o.j.q.p.Router [0.6/0.6]
     prepare: c.o.a.PrepareContext [1.7/2.4]
     prepare: c.o.a.InsertRulesInDB [21.8/24.2]
     prepare: o.j.q.SendResponse [0.1/24.4]
     prepare: c.o.a.TriggerMerchantBlockCacheReload [60241.7/60266.1]
      commit: c.o.a.PrepareContext [0.1/60266.2]
      commit: c.o.a.InsertRulesInDB [0.0/60266.3]
      commit: o.j.q.SendResponse [0.8/60267.1]
      commit: c.o.a.TriggerMerchantBlockCacheReload [0.0/60267.1]
     end [1.2/60268.3]
   </profiler>

So the question is why does the prepare not do anything in the SendResponse participant?

@barspi
Copy link
Contributor

barspi commented Mar 11, 2024

SendResponse does its main job in the "closing phase" of the two-phase commit protocol.
That could be either a commit or abort.
It's good to do it there (and to allow it to happen even if a previous participant aborted it) because that's when you have enough information to create your response.

I don't know what you're doing in your TriggerMerchantBlockCacheReload.
If it's not related to the transaction, maybe you can choose to

  1. do the work also during commit/abort (instead of prepare)
  2. do the work asynchronously, for example by preparing some work payload and sending it to a queue from where a "TriggerMerchantBlockWhatever" QBean will be reading in its own thread and doing the work in a concurrent thread, after the transaction has happened.

@mchhil-incomm
Copy link
Author

mchhil-incomm commented Mar 12, 2024

Thanks for responding @barspi
Could the identical code in commit and abort be moved to prepare and call prepare from abort and remove the commit call?

Option 2 was my backup though the long running participant is ideally part of the transaction :)

Suggestion

 public int prepare(long id, Serializable context) {
        sendHTTPResponse(context);
        return PREPARED | READONLY;
    }

    protected void sendHTTPResponse(Serializable context) {
        Context               ctx      = (Context) context;
        ChannelHandlerContext ch       = ctx.get(SESSION);
        FullHttpRequest       request  = ctx.get(REQUEST);
        FullHttpResponse      response = getResponse(ctx);
        sendResponse(ctx, ch, request, response);
    }

    @Override
    public void abort(long id, Serializable context) {
        sendHTTPResponse(context);
    }
    // don't call it in commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants