-
Notifications
You must be signed in to change notification settings - Fork 55
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
Processor and Checkout refactoring #172
Conversation
69c62cf
to
21dbc3a
Compare
90ee35e
to
aa5740b
Compare
3e46071
to
9b50003
Compare
9b50003
to
5d54382
Compare
The processor was way too complicated, taking on too many responsibilities. As a result, it was complex to reason about and it was a very brittle part of the extension. The new processor simply does two things: it finds all actionable subscriptions and ensures to take the appropriate action on them (e.g., cancel, deactivate), including creating the new installment for later. Then, it finds all the actionable installments (including the ones that were just created), and schedules them for asynchronous processing. One side effect of this refactoring is that installments are not grouped by address and payment method/source anymore: each installment will always correspond to a new order. Any logistics-related optimizations should be implemented by the individual store.
3bc40c3
to
8e1f61d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great work, @aldesantis! 👏 🎉
It took me a while to review it. I wasn't familiar with the old code. What I can say is that the new version is much easier to follow.
@@ -0,0 +1,11 @@ | |||
RSpec.describe SolidusSubscriptions::ProcessInstallmentJob do | |||
it 'creates an order for the installment' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name of this test confused me a little bit. The test itself does not check for any new orders.
Maybe processes checkout for the installment
? Am I missing something? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I think this used to be an integration test and then I stubbed out the checkout service object. I'll fix the description!
Instead of attempting to process multiple installments at a time, which increases the chances something might go wrong, we are now only processing one installment at a time. This also improves the extension's performance, because the installments can be processed in parallel.
This service object contained a lot of indirection and took on too many responsibilities. The new version is much more streamlined and the flow of operations should be much clearer.
By setting the queue through a block rather than a boot-time method call, we ensure to play nicely with configuration stubs and in other non-obvious scenarios.
Because it's very business-specific, this kind of change should be done at the application level in a decorator, rather than embedding it in the extension.
It wasn't clear why certain business logic should live in `app/services` while other should live in `lib`. By unifying everything in one directory, we make it easier for developers to inspect the code and reduce the cognitive load when implementing new classes.
These helpers are dangerous: they provide a false sense of assurance by making you think that the order and the line item they return can be used to infer the correct total value of future subscription orders. In reality, order calculation in Solidus is an extremely complex process that may take a ton of different parameters into account, and each store is better off calculating the subscription total with their custom logic rather than this extension trying to provide a solution that works for everyone. In the future, we may provide a way to compute a subscription's total, but for the time being it's better to remove the helpers altogether.
d86364e
to
4717d24
Compare
@igorbp should be good for another review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @aldesantis! LGTM
There are some tests breaking but I don't think it's related 🤔
This is a pretty extensive refactoring of two critical service objects in the extension:
Processor
, which creates and acts on installments, andCheckout
, which creates orders to fulfill installments.I have streamlined and simplified both, because the code was very hard to follow and the chance of introducing subtle bugs when touching it was quite high.
A bunch of other APIs and service objects have also been cleaned up and streamlined in the process (e.g., dispatchers, line item builder).