Skip to content

Comments

[WOOMOB-2061] Add analytics tracking for file-based catalog sync#15288

Draft
malinajirka wants to merge 15 commits intotrunkfrom
woomob/add-file-based-catalog-analytics
Draft

[WOOMOB-2061] Add analytics tracking for file-based catalog sync#15288
malinajirka wants to merge 15 commits intotrunkfrom
woomob/add-file-based-catalog-analytics

Conversation

@malinajirka
Copy link
Contributor

@malinajirka malinajirka commented Feb 4, 2026

Fixes WOOMOB-2061

Description

Adds analytics tracking for the file-based local catalog sync to help diagnose "stuck" sync issues. When sync times out or fails, we now track additional properties to understand where the sync got stuck:

  • generation_duration_ms: How long the catalog file generation took on the server
  • poll_attempts: Total number of poll attempts (persisted across app restarts)
  • last_generation_state: The last state received from the server when timeout occurs

Poll attempts are accumulated across app restarts so we can see the total attempts when users repeatedly open/close the app during long syncs.

Based on pdfdoF-8GW-p2.

Test Steps

  1. Enable file-based local catalog sync feature flag
  2. Trigger a catalog sync (enter POS mode or trigger it in catalog settings)
  3. Verify sync completion events include the new properties when using file-based sync
  4. Force a timeout scenario and verify failure events include last_generation_state and poll_attempts (easiest way to force it is to update the code, however, I tested it by scheduling a job and before it started I cancelled it in WPAdmin -> WooCommerce -> Status -> Scheduled Actions -> Pending -> Search for feed` -> cancel catalog generation action)

Images/gif

N/A - Analytics changes only

  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

Extend the sync_strategy analytics property to distinguish file-based
local catalog sync from paginated sync. This allows filtering analytics
by sync method to identify performance issues with file-based approach.

- Add LOCAL_CATALOG_FILE to SyncStrategy enum
- Inject WooPosLocalCatalogFileApproachEnabled to determine sync method
- Update analytics mapping to include "local_catalog_file" value
- Update exhaustive when expressions in search and identifier lookup
Extend Success class with optional generationDurationMs and pollAttempts
for tracking server-side generation time and polling attempts.

Extend CatalogGenerationTimeout with lastGenerationState and pollAttempts
to track the last observed state before timeout for debugging.
Add site-specific methods to persist poll attempts across worker retries:
- getFileBasedSyncPollAttempts: read accumulated attempts
- setFileBasedSyncPollAttempts: store attempts count
- clearFileBasedSyncPollAttempts: reset after successful sync

This ensures poll_attempts continue accumulating when the worker retries
after a timeout instead of resetting to 0.
Add calculateGenerationDuration method to compute server-side generation
time from scheduledAt and completedAt timestamps. Returns the difference
in milliseconds for tracking slow catalog generation.
- Read accumulated poll attempts from preferences at sync start
- Track current run poll attempts and accumulate with previous retries
- Track last generation state (scheduled/in_progress/completed) for timeouts
- Calculate generation duration from API timestamps (completedAt - scheduledAt)
- Pass poll attempts and generation duration to Success result
- Pass last generation state and poll attempts to CatalogGenerationTimeout
- Clear poll attempts on success, persist on timeout for next retry
Update LocalCatalogSyncCompleted event:
- Add optional generationDurationMs for server-side generation time
- Add optional pollAttempts for number of polling attempts

Update LocalCatalogSyncFailed event:
- Add optional lastGenerationState for timeout debugging
- Add optional pollAttempts for tracking retry accumulation

Properties are only included when non-null (file-based sync only).
Update trackSyncCompleted to include:
- generationDurationMs from Success result
- pollAttempts from Success result

Update trackSyncFailed to include:
- lastGenerationState from CatalogGenerationTimeout
- pollAttempts from CatalogGenerationTimeout
Update checks that compared against LOCAL_CATALOG to use != REMOTE
instead, so they work correctly for both LOCAL_CATALOG and
LOCAL_CATALOG_FILE sync strategies.
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Feb 4, 2026

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App NameWooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commit8c261aa
Direct Downloadwoocommerce-wear-prototype-build-pr15288-8c261aa.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Feb 4, 2026

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

App NameWooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commit8c261aa
Direct Downloadwoocommerce-prototype-build-pr15288-8c261aa.apk

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt
- Simplify poll attempt logic by removing `currentRunPollAttempts`.
- Use `attemptIndex` consistently in logs and calculations.
- Consolidate total poll attempts calculation for timeout handling.
@malinajirka malinajirka added category: tracks Related to analytics, including Tracks Events. feature: POS labels Feb 4, 2026
@malinajirka malinajirka added this to the 24.1 milestone Feb 4, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds additional analytics metadata for the file-based local catalog sync to better diagnose “stuck” generation/polling scenarios, including generation duration, total poll attempts, and last-known generation state on timeout.

Changes:

  • Extend local catalog sync result and analytics events to include generation_duration_ms, poll_attempts, and last_generation_state (timeout).
  • Persist poll attempt counts in DataStore and wire them into the file-based sync action + tests.
  • Introduce/propagate a new LOCAL_CATALOG_FILE sync strategy across UI/analytics decision points.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosFileBasedSyncAction.kt Computes/passes poll attempts, tracks last generation state, stores attempts on timeout, computes generation duration.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosLocalCatalogSyncRepository.kt Sends new optional analytics properties on completed/failed events (timeout-only for failure props).
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosSyncResult.kt Extends success + timeout failure result types with new optional fields.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/analytics/WooPosAnalyticsEvent.kt Adds optional properties for completed/failed local catalog sync analytics; adds mapping for LOCAL_CATALOG_FILE.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt Adds DataStore persistence helpers for file-based sync poll attempts.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosSyncTimestampManager.kt Adds helper to compute generation duration from API timestamps.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt Adds LOCAL_CATALOG_FILE sync strategy and determines it via feature flag.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/categories/WooPosSettingsCategoriesViewModel.kt Shows Local Catalog settings category for any non-remote strategy (includes file-based).
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/search/WooPosItemsSearchViewModel.kt Enables PTR for both local catalog strategies.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/data/searchbyidentifier/WooPosSearchByIdentifier.kt Avoids remote fallback whenever using a non-remote sync strategy.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/data/searchbyidentifier/WooPosSearchByIdentifierLocal.kt Treats LOCAL_CATALOG_FILE like LOCAL_CATALOG for local search behavior.
WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosFileBasedSyncActionTest.kt Adds coverage for persisted poll attempts, generation duration, and timeout last-state propagation.
WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSourceTest.kt Updates construction for the new feature-flag dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +47 to +49
val siteId = site.localId()
val accumulatedPollAttempts = preferencesRepository.getAndClearFileBasedSyncPollAttempts(siteId)
var lastGenerationState: WooPosGenerateCatalogState? = null
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

getAndClearFileBasedSyncPollAttempts() clears the persisted counter at the start of a run, but most non-timeout failure paths (e.g., consecutive network failures, download/parse/store failures, missing URL) return without re-persisting the updated count. This can drop previously accumulated attempts and defeats the “accumulated across app restarts” behavior. Consider reading without clearing, incrementing as you poll, and only clearing on successful completion (or re-saving the latest total on any early exit/failure).

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +166
val timeoutResult = result as? PosLocalCatalogSyncResult.Failure.CatalogGenerationTimeout

analyticsTracker.track(
LocalCatalogSyncFailed(
syncType = syncType,
errorContext = "WooPosLocalCatalogSyncRepository",
errorType = errorType,
errorDescription = result.error
errorDescription = result.error,
lastGenerationState = timeoutResult?.lastGenerationState,
pollAttempts = timeoutResult?.pollAttempts
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The new failure analytics properties (lastGenerationState, pollAttempts) are only populated when the failure is CatalogGenerationTimeout (via the cast). Other file-based sync failures will still emit local_catalog_sync_failed without these properties, which doesn’t match the PR description (“times out or fails”). Either propagate these properties for other failure types too (e.g., by carrying pollAttempts/last state in a shared failure type) or adjust the PR description to clarify it’s timeout-only.

Copilot uses AI. Check for mistakes.
@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 65.00000% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.86%. Comparing base (b369c32) to head (8c261aa).

Files with missing lines Patch % Lines
...opos/util/datastore/WooPosPreferencesRepository.kt 0.00% 15 Missing ⚠️
...i/woopos/localcatalog/WooPosFileBasedSyncAction.kt 84.84% 0 Missing and 5 partials ⚠️
...d/ui/woopos/util/analytics/WooPosAnalyticsEvent.kt 80.00% 1 Missing and 4 partials ⚠️
...oopos/util/datastore/WooPosSyncTimestampManager.kt 0.00% 4 Missing ⚠️
...os/home/items/products/WooPosProductsDataSource.kt 40.00% 3 Missing ⚠️
...s/localcatalog/WooPosLocalCatalogSyncRepository.kt 57.14% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##              trunk   #15288   +/-   ##
=========================================
  Coverage     38.85%   38.86%           
- Complexity    10729    10730    +1     
=========================================
  Files          2214     2214           
  Lines        125980   126046   +66     
  Branches      17465    17479   +14     
=========================================
+ Hits          48954    48984   +30     
- Misses        72072    72098   +26     
- Partials       4954     4964   +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samiuelson samiuelson self-assigned this Feb 5, 2026
@malinajirka malinajirka modified the milestones: 24.1, 24.3 Feb 6, 2026
@malinajirka
Copy link
Contributor Author

📓 This can wait for after the Bookings work.

@malinajirka malinajirka marked this pull request as draft February 6, 2026 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: tracks Related to analytics, including Tracks Events. feature: POS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants