Skip to content

Instantly share code, notes, and snippets.

@ctrahey
Created June 29, 2021 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ctrahey/2d04992f10e6403f51936ee9ba6d82d9 to your computer and use it in GitHub Desktop.
Save ctrahey/2d04992f10e6403f51936ee9ba6d82d9 to your computer and use it in GitHub Desktop.
First, I want to advocate for a 'decoupled' solution, where instead of directly trying to print when you get a new order, you instead have a task that tries to print all orders which have not yet been printed (possibly with some sanity checks like "received in the last 24 hours and also not yet printed"
The reason I suggest this is that it isolates the two parts of code from each other's errors. For example, if the printing code fails or takes a while to finish, does it delay the order processing? This kind of decoupling is a key feature of designing robust systems.
To achieve this, you will first need some code that can take an order and get it printed. How you do this depends greatly on your specifics, so I'll leave the details up to you (possibly with a different, more specific SO question to help). The main "requirements" for this component is that it takes in an order, and reports back if it was successful or not.
Then your database should have a way to track if an order was printed. From experience I can tell you that the instinct to add a "printed" boolean column is worth avoiding. There is an entire discipline associated with making modeling decisions like this, but suffice it to say that since the printed-or-not status of an order is not directly part of what makes an order an order, and thus it should not be a column on the orders table. You'll likely want an "order_prints" table or similar, where there is a key for order_id and then maybe a date column representing when the order was successfully printed. The absence of a row in this table for an order implies that it has not been printed. This is not the only way to model this, but wanted to get you thinking in this direction.
Lastly, you want a way to trigger the print job. The old way of doing this would be to call into it from your order processing code. This is not the best for the reasons described earlier - you want any bugs in your printing code completely isolated from your business-critical order processing code.
The more modern way might be to have your order processing code send out a message to a message queue that the printing code is listening to. This is quite advanced though, and could be overkill.
The middle ground is to have the printing code run on a periodic basis (e.g. via cron job), and it starts with a query selecting all orders placed recently that don't have a record in the order-prints table, and then prints them. On success, it adds these records so that the order is not printed next time.
There are caveats and edge cases to this solution. One that comes easily to mind is that if your printing code takes too long, it could end up running multiple times "overlapping" and multiple instances could select the same order to print. There are a couple ways to solve this, including row-level database changes like tracking when a print job is in progress... having the print job only select 1 job, marking it in progress, etc. Another way is to have the print job run all the time (an infinite loop that is constantly trying to select the oldest non-printed order, sleeping for 1 minute whenever it doesn't find one... etc.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment