Crustecan Warrior MVP

Transaction management.

The dashboard page with all of its features have been implemented quite successfully. With that, I will declare the completion of Crustecan Warrior app. Although I say “completion”, I’ve only finished the main functionalities such as ticket checkout and its data management system. But as it stands, people can start using it. Or any sports team which needs an online ticket order system can benefit from it. It’s definitely usable, but it’s far from appropriate. And that’s why I still need to refine it a whole lot more so that it’s much more pleasant to use.

Before finishing the dashboard page and thus conclude the Minimum Viable Product (MVP), I had a case problem in my transaction cancellation algorithm. To sum it up, I had a race condition. For my credit card checkout, which is the only one I have for now, I’m using Stripe checkout session. Each of ticket order will create its own session and each of these will have an amount of time before it gets expired. To explicitly cancel these sessions, I can only do that using Stripe’s JavaScript SDK “expiry” method. Eh, quite straightforward, isn’t it?

Now let me introduce you to Stripe hook. It’s an event emitter that will fire all sorts of business critical events such as “payment accepted” and in my case “session expired”. You first need to create an endpoint in your server to listen to these Stripe events, and then you can configure your Stripe hook through your Stripe account dashboard to forward all the events to your previously created endpoint. In your server endpoint, you can differentiate between different event types and handle each of them according to your needs. Again, simple as it is.

Now, let’s go back to my main requirements.

  1. I need to handle the automatic session expiration emitted from Stripe.
  2. I need to have a way to explicitly cancel a certain session.

The mainline for these requirements is both will trigger a “session expiration” event and inevitably visit my server’s hook listener. I initially thought that it will be fine to leave all the cancellation logic such as re-enabling ordered seats and changing the transaction status to “cancelled” from inside my server’s hook listener. That way, I can channel all of the session expiration logic into the hook listener function and call it a day. Oh yes, I need to say that this is working quite perfectly as I intended to be. But that conviction changed when I learn about RTK Mutations.

In my previous post, I talk a bit about RTK cache behavior. Basically, if I want to use its data mutation feature, I need to invalidate the cache data to tell RTK to refetch the new data once the mutation is completed. To cancel a transaction, I need to hit my “/user/transaction/:id/cancel” route. All this route does is to simply call the Stripe SDK’s “expire” method and return an “ok” response. It doesn’t need to do anything else because remember, I put all the transaction cancellation algorithm inside my Stripe hook listener route. Since the cancel transaction route only return an “ok” response, RTK quickly do a refetch to get the newest data. Lo and behold, the refetch does not get the latest data. Wait, it actually gets the latest data possible from the database, so my previous explanation isn’t quite precise. It gets the latest data, but the transaction cancellation algorithm hasn’t finished its job when the request for new data arrives.

Honestly, I feel reluctant in fixing this problem. No, it’s not that I’m lazy, but I really loved the idea of putting the cancellation algorithm inside the Stripe hook listener route. The idea of piping multiple outlets to the same function turns me on (pardon me). The only solution inside my head for now is to do duplication of code, which is passing the same transaction cancellation function to both cancel route and Stripe session expiration event listener. And worse still, since I’m calling the “expiry” method from cancel route, it will also trigger a session expiration that the hook listener will inevitable handle too. That means, I’m running the transaction cancellation function twice. One in cancel route and the other in the Stripe hook listener. Of course, you can prevent this from happening by creating a decision block on transaction status. If the status is still “open”, then run the algorithm. No problem. I just feel a bit itchy when I see a seemingly unnecessary repetition in my code.

Well, that little mishap conclude the dashboard page and thus completes the MVP for Crustecan Warrior app. From here onwards, I will do my best to refine it further with CSS works and additional little features which sparked in my mind throughout development process. Thank you for reading my post and have a nice day.

Published by YosepRA

I'm a MERN stack web developer. I will build a web application to turn your online ideas into reality.

Leave a comment

Design a site like this with WordPress.com
Get started