Skip to content

Add option to fetch lightweight objects to reduce app hangs #15774

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

Open
wants to merge 9 commits into
base: trunk
Choose a base branch
from

Conversation

itsmeichigo
Copy link
Contributor

@itsmeichigo itsmeichigo commented Jun 18, 2025

Closes WOOMOB-619

Description

There have been warnings from Xcode about performing I/O on the main thread causing app hangs. Xcode Organizer also shows reports about app hangs related to this:

image

The stack traces point to ResultsController.fetchedObjects and ResultsController.object(at:), which then triggered Product.toReadOnly() and Order.toReadOnly in different areas of the app. These are heavy objects with complicated relationships that require multiple trips to the database file to fetch all data. Since we're doing all the fetches on the main thread, fetching multiple such heavy objects can cause app hangs.

This PR attempts to mitigate the issue by introducing the option to fetch lightweight objects - i.e., fetching objects without populating all their relationships. These are helpful for list views and other scenarios when it's not necessary to retrieve all the details of objects. This reduces the overhead of loading objects and thus minimizes app hangs.

Updated areas (following reports on Xcode Organizer and Xcode warnings):

  • Loading order details: OrderDetailsDataSource.reloadSections()
  • Checking shipping labels eligibility: OrderDetailsViewModel.localRequirementsForShippingLabelsAreFulfilled()
  • Checking for published products on order list: OrderListViewModel.hasAnyPublishedProducts
  • Blaze campaign creation form
  • Dashboard check for order count
  • New shipping label purchase form: WooShippingItemsDataSource
  • Product list

Testing steps

Confirm that you can no longer see warnings about performing I/O on the main thread on Xcode while running the following test cases. It's not predictable when Xcode shows the app hang warnings, so we may need to wait for app hang reports after releasing the app. For now, we can do regression testing to ensure that the app works correctly with the new changes.

TC1: Loading order details

  • Navigate to the Orders tab
  • Select a non-refunded order and confirm that the order items are listed correctly.
  • Select a refunded order and confirm that the details are displayed correctly.

TC2: Shipping Labels

  • Pre-requisite: Install the WooShipping extension on your test store and log in to the same store on the app as the store owner.
  • Navigate to the Orders tab and select a paid order with at least one physical product.
  • Confirm that the Create shipping label button is available.
  • Select Create shipping label button.
  • Confirm that the purchase form displays the correct products.

TC3: Test order entrypoint

  • Create a test store if you don't already have access to a store without any published products.
  • Enable cash on delivery payment for the store if it doesn't have any payment gateways yet.
  • Ensure that the store is public.
  • Log in to that test store on the app and navigate to the Orders tab. Confirm that the empty state screen has a button to create a test order.

TC4: Blaze campaign creation form

  • Log in to a WPCom store or install Blaze extension to your self-hosted store.
  • Navigate to the Products tab and select any published product.
  • Select Promote with Blaze.
  • Confirm that the campaign creation form displays the correct product image and relevant tag line and description for the product.
  • Select Ad Destination and confirm that the product URL is correct for the product.

TC5: Dashboard order count

  • Log in to a test store with no existing order.
  • Confirm that the Performance and Top Performers cards are not available on the dashboard and in the Dashboard > Edit list.
  • Create a new order in the store.
  • Confirm that the Performance and Top Performers cards are now available.

TC6: Product list

  • Build and run the app on an iPad
  • Log in to a test store with existing products.
  • Navigate to the Products tab.
  • Confirm that the first product on the list is selected automatically. Confirm that the details displayed on the product form are correct.
  • Confirm that the product list displays correct details for the items.

Testing information

Screenshots

No UI changes.


  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

@itsmeichigo itsmeichigo added this to the 22.7 milestone Jun 18, 2025
@itsmeichigo itsmeichigo added feature: core Core work. See "category: tooling" and "category: architecture" Enhancement labels Jun 18, 2025
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Jun 18, 2025

App Icon📲 You can test the changes from this Pull Request in WooCommerce iOS Prototype by scanning the QR code below to install the corresponding build.

App NameWooCommerce iOS Prototype
Build Number30609
VersionPR #15774
Bundle IDcom.automattic.alpha.woocommerce
Commitc65ddb4
Installation URL4pntvkqvck2bo
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@itsmeichigo itsmeichigo marked this pull request as ready for review June 19, 2025 05:43
@itsmeichigo
Copy link
Contributor Author

itsmeichigo commented Jun 19, 2025

@jaclync I could not see the warnings regarding the product list as you reported, so could you please verify if this PR fixes that for you?

Copy link
Contributor

@RafaelKayumov RafaelKayumov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Снимок экрана 2025-06-19 в 16 31 53

I can see the I/O warning too. I guess that's because there are still code paths utilizing the "heavy" version of the toReadOnly. Putting print logs both into the toReadOnly and toLightweightReadOnly for Product and Order correspondingly reveal that the old method is still extensively used.

Mostly I see it in Order List tab.

Снимок экрана 2025-06-19 в 17 09 03

I logged timings both for the heavy and lightweight readonly conversion. Looks like the light version works roughly ~10x faster. Is it a good trade-off for the fact that the "light" stripped down versions are the same "plain" objects, but just not containing relationships, and it's quite easy to treat them as complete objects and misuse them.

I wonder if we could also go for a more fundamental refactoring and make the toReadOnly conversion completely async, i.e. obtaining a Core Data object by NSManagedObjectID from a private context, doing conversion in a background and returning the result since the plain object is thread-safe? Though I doubt that we can afford it at the moment.

@itsmeichigo
Copy link
Contributor Author

itsmeichigo commented Jun 20, 2025

Thank you @RafaelKayumov for the review.

it's quite easy to treat them as complete objects and misuse them

I understand the concern. From my POV, this is similar to having a separate model that is used for list view versus a full model for a details screen. It's up to the developers to decide which to use and test their work.

I wonder if we could also go for a more fundamental refactoring and make the toReadOnly conversion completely async, i.e. obtaining a Core Data object by NSManagedObjectID from a private context, doing conversion in a background and returning the result since the plain object is thread-safe? Though I doubt that we can afford it at the moment.

This is one of the options that @jaclync proposed when she reported WOOMOB-619. I agree that it seems to be a more reliable solution, but it comes with the complexities of handling asynchronous logic, and requires refactoring how we use fetched objects all around the app. I'd prefer keeping the logic synchronous to be more expectable and easier to maintain.

Moreover, it seems like a waste of resources to try to get all the properties where they are not needed, so I chose the solution in this PR instead.

Mostly I see it in Order List tab.

Thanks for catching this! I didn't see the warning on my side. Added a change to the order cells to use the lightweight version of the objects in c65ddb4. Could you try again and see if the warning goes away?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement feature: core Core work. See "category: tooling" and "category: architecture"
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants