-
Notifications
You must be signed in to change notification settings - Fork 109
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
Fix Custom Fields Handling in Storage for both Orders and Products #14111
Fix Custom Fields Handling in Storage for both Orders and Products #14111
Conversation
…ields` - Update comment to clarify the removal process of custom fields in `handleProductCustomFields`
…ore.swift` - Creates a new array to store new metadata objects before adding to `storageProduct`
…ad-only product - Update logic to only handle new custom fields from read-only product
- Streamline logic for removing custom fields that are not in read-only product
- Optimize custom fields handling in OrdersUpsertUseCase.swift - Replace forEach with a set lookup to improve performance - Introduce batch writing for new custom fields to reduce database calls
Generated by 🚫 Danger |
📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.
|
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 for working on this, Paolo!
I tested this on a store with a large number of custom fields and I validated that orders are loaded as expected. ✅
I will wait for @hafizrahman to test that custom fields are displayed without issues.
return newStorageMetaData | ||
} | ||
|
||
// Batch writing process of multiple custom fields |
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.
Nice. 👍
storage.deleteObject(storageCustomField) | ||
} | ||
|
||
// Create `customFields` objects from the `readOnlyOrder` |
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 think we should unit tests to OrdersUpsertUseCaseTests
to validate that it can handle a large number of MetaData
items. Right now, I see only tests that add/remove 1 custom field. What do you think?
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.
Implemented here dd9ca23
storage.deleteObject(storageCustomField) | ||
} | ||
|
||
// Create `customFields` objects from the `readOnlyProduct` |
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.
Similar to the other comment. I think we should unit tests to validate that it can handle a large number of MetaData items.
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 test implemented here dd9ca23 should work also for Products
At this point in this branch, the Product Details is not able to actually show custom fields yet (only shows entry point), with the logic to show them is in a different branch in #14068 However, I was able to test this by putting a breakpoint inside Update: additionally, loading the product list screen itself also works fine. This is tested in both iPad and iPhone in iOS 17.5 Simulator with a site with many orders and products, where the products have many custom fields. |
@pmusolino Please update the PR description to close the issue #14106 |
…ducts - Modify `OrdersUpsertUseCaseTests.swift` to include a new test case for processing 5000 custom fields without deadlock.
@selanthiraiyan ready for another check |
|
||
// Batch writing process of multiple custom fields | ||
if !newStorageMetaDataArray.isEmpty { | ||
storageOrder.addToCustomFields(NSSet(array: newStorageMetaDataArray)) |
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.
@pmusolino Just sharing an observation from some debugging - this line caused the upsert to be triggered twice, with newStorageMetaDataArray
containing a different custom field object (different Core Data object ID) each time. It's the expected result of the updated approach in this PR, with pre-existing custom fields being deleted and new custom fields re-added.
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, Jaclyn!
From the comment of the failing unit test I wonder whether the updated approach of deleting all the stored custom fields before adding new custom fields will cause any reload or UI issues in screens where we use EntityListener
to listen to changes to product or order entities. 🤔
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 a lot for working on this @pmusolino and @itsmeichigo! I appreciate the efforts. 🙇
With the new approach of deleting all the MetaData
items from Storage we are not doing the "upsert" operation of orders and products. i.e. We are not following the "upsert" behaviour, which is to check the existing items from core data and update them. Instead, we delete all the MetaData
items and add them again regardless of whether something changed.
I think we should look for a different solution for the following reasons.
- The existing method names and comments expect an upsert operation instead of deleting everything. This is misleading.
- Core data will consider that the entity is changed even if we write the same order or product into the storage again. (which triggers callbacks and UI reloads) This is not expected from an "upsert" process.
Unfortunately, I don't have any suggestions currently.
- Update `OrdersUpsertUseCase.swift` to upsert custom fields from `readOnlyOrder`. - Update `ProductStore.swift` to upsert custom fields from `readOnlyProduct`. - Remove redundant custom fields from both `storageOrder` and `storageProduct` based on `readOnlyOrder` and `readOnlyProduct`.
@selanthiraiyan I have pushed new changes here: 3cc83fd. In this update, |
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 looks great! 👏
I tested it using the store with issues, and the orders load as expected.
DispatchQueue.global(qos: .background).async { | ||
orderUseCase.upsert([order]) | ||
productStore.upsertStoredProducts(readOnlyProducts: [product], in: backgroundContext) | ||
backgroundContext.saveIfNeeded() |
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.
nit: Indentation update needed.
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.
Closes #14106
Description
It has been reported that for some users orders does not load peaMlT-Wz. It seems that this can happen when a store has a lot of custom fields for products, so upserting custom fields creates a deadlock on the writer context, delaying the syncing of orders for around 2 minutes.
This update optimizes the handling of custom fields in both
OrdersUpsertUseCase
andProductStore
. The changes improve performance by streamlining the logic for managing custom fields, introducing batch processing, and eliminating redundant operations.Summary of changes
OrdersUpsertUseCase
storageOrder
that are not present inreadOnlyOrder
, directly removing them to simplify the logic.ProductStore
readOnlyProduct
by directly using a set lookup.Steps to reproduce
Testing information
Tested that in a store with a lot of custom fields for products and orders, and everything loads properly.
RELEASE-NOTES.txt
if necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: