-
Notifications
You must be signed in to change notification settings - Fork 120
Order details: Fix crash when reloading orders #15764
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
Order details: Fix crash when reloading orders #15764
Conversation
|
|
RafaelKayumov
left a comment
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.
Looks good. I have a few questions.
The change extends the “state” nature of the OrderDetailsDataSource.
I wonder if it’s necessary to also make sure the state refreshed (reloadSections() called) after modifying the order of the OrderDetailsDataSource instance.
For example in:
func update(order: Order) {
self.order = order
resultsControllers.update(order: order)
}
and in
func configureResultsControllers(onReload: @escaping () -> Void) {
resultsControllers.configureResultsControllers(onReload: onReload)
}
I didn't dive to deep. But it feels like those methods should be coupled with the reloadSections()
Also the lookUpProductVariation(...) relies on readonly value taken from resultsControllers.productVariations which is a fetched property and can potentially vary as a result of a race condition.
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.
(Non-blocking)
Just checking the code changes. Is the crash reproducible before this PR? Are the repro steps different from the one fixed previously? If so, I wonder why it was fixed back then but not anymore.
Using resultsController's properties which are struct type feels promising, but I was wondering if we could try not saving them as variables that can be mutated any time.
| shippingLabelOrderItemsAggregator = AggregatedShippingLabelOrderItems( | ||
| shippingLabels: shippingLabels, | ||
| orderItems: items, | ||
| products: products, |
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.
❓ How is this products different from the products below in L1195? Shall we use the same products in the beginning of the function?
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.
Good point - addressed in dc7f0dc.
| refunds = resultsControllers.refunds | ||
| customAmounts = resultsControllers.feeLines | ||
| orderTracking = resultsControllers.orderTracking | ||
| currentSiteStatuses = resultsControllers.currentSiteStatuses | ||
| products = resultsControllers.products | ||
| addOnGroups = resultsControllers.addOnGroups | ||
| siteShippingMethods = resultsControllers.siteShippingMethods |
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.
How about also freezing order (and its items among other properties used in the sections) in case the order changes in the middle?
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.
This probably requires some refactoring, but I was wondering if a crash could still happen when there are two reloadSections at the same time, and because they're async, the second call can overwrite the variables and the first call can use the updated values later on? If we want to freeze the values, it might be better passing them to functions called in reloadSections that depend on them instead of saving them as variables so that these values aren't mutable for the whole reload function.
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.
I'm struggling to understand your suggestions here, so it'd be nice if you could clarify your suggestions further.
From my understanding, it'd be simpler if the reloadSections method were synchronous - that way, every reload would be subsequent and more predictable. Another refactoring idea is to udpate createPaymentSection to be synchronous and adjust the payment section when the receipt row is available. That could be simpler - WDYT?
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.
If we want to freeze the values, it might be better passing them to functions called in reloadSections that depend on them instead of saving them as variables so that these values aren't mutable for the whole reload function.
The variables are also accessed when configuring cells, so it cannot be a simple as passing them through to determine sections.
|
@RafaelKayumov Regarding your suggestion:
I think the purpose is to decouple the logic, as the calls are triggered from the higher in the hierarchy: OrderDetailsViewController > OrderDetailsViewModel > OrderDetailsDatasource > OrderDetailsResultsControllers. The view controllers triggers table view reload when there's a change to the order object: Lines 204 to 212 in c8788ef
The view controller also triggers table view reload upon results controller updates: Lines 219 to 221 in c8788ef
Good catch! Moved product variations to a property in dc7f0dc. |
|
Thanks for taking a look @jaclync.
The issue back then was 100% reproducible. The issue this PR is trying to address is more of a timing issue. The app crashes only when the refund update comes in the middle of a reload. I responded to your other questions in the corresponding threads. |

Closes WOOMOB-604
Description
Previously, there was an attempt to fix the crash when reloading the order details screen. This mitigated some of the cases but the same crash still happens sometimes after refunding a cached order and reloading the same order.
The crash is due to the use of computed variables in
OrderDetailsDataSource. For the case with refunding, the app would crash in the following scenario:OrderDetailsDataSourcedetermines the sections inreloadSections.aggregateOrderItemscomputed property returns an empty array due to the refund.=> The app crashes when configuring order items with index out of bounds error.
Screen.Recording.2025-06-17.at.12.35.16.mov
The solution is to freeze all access to the results controllers upon
reloadSectionsto avoid discrepancies when reloading data.Testing steps
Since the crash happens depending on the timing of the refund syncing, so ensure to do a few tries to confirm.
Testing information
Tested and confirmed the fix on simulator iPhone 16 iOS 18.4
Screenshots
Screen.Recording.2025-06-17.at.14.57.19.mov
RELEASE-NOTES.txtif necessary.