Skip to content

MS-1537 Bonus refactoring - device state tracker - #1845

Open
luhmirin-s wants to merge 10 commits into
mainfrom
feature/MS-1537-hearthbeat-request
Open

luhmirin-s wants to merge 10 commits into
mainfrom
feature/MS-1537-hearthbeat-request

Conversation

@luhmirin-s

@luhmirin-s luhmirin-s commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ticket
Will be released in: 2027.1.0

This change is a ground work to simplify/unify local device data state collection for the "hearthbeat" worker. Since the required data is very close to what we already collect for sync dashboard, it makes sense to move this part out of dashboard to a common infra layer.

Notable changes

  • New DeviceStateDataTracker (infra/sync/devicestate) — single entry point for "how much data is on this device", replacing SyncableCounts/ObserveSyncableCountsUseCase (both deleted). Exposes a conflated flow for UI and one-shot methods for calls in worker.
    • An unreadable source stays null and is never collapsed to 0, since the distinction decides whether a device is holding data at risk. Rendered as "unknown" in the UI.
    • Added SyncOutcome and SyncFailureReason in infra/core to use across modules.
  • EventSyncCache and ImageSyncTimestampProvider now persist last attempt (with failure reason) alongside the existing last success key, each observable as a flow. The old completion key is preserved so upgrading devices keep their history; attempt keys start empty.
  • Added OUTPUT_FAILED_UNEXPECTEDLY worker failure reason, plus List<WorkInfo>.firstFailureReason() mapping worker output to SyncFailureReason.
  • Add a reactive DAO query for per-scope-type event counts so pending scopes stream from Room instead of being polled.
  • Migrated dashboard sync info, AboutViewModel, UpdateSessionScopePayloadUseCase (session-scope record count), and the project-ending sign-out gate in HandleProjectStateUseCase (fixes a stale event count there) all go through the tracker. * Troubleshooting overview gained a device-data-state section for manual monitoring.
  • ImageSyncTimestampProvider is now a @Singleton with IO-dispatched, suspending reads and lazy prefs, where it was previously synchronous on the caller's thread.

Testing guidance

  • Down-sync some records on the device and run some sessions (both enrol and ID) as well as change the language (device scope) and upload samples (sample upload scope).
  • Numbers in the dashboard and troubleshooting screen should reflect actions in the app.

Additional work checklist

  • Effect on other features and security has been considered
  • Design document marked as "In development" (if applicable)
  • External (Gitbook) and internal (Confluence) Documentation is up to date (or ticket created)
  • Test cases in Testiny are up to date (or ticket created)
  • Other teams notified about the changes (if applicable)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Resolve the two critical tracker issues and preserve coroutine cancellation handling.

Review effort: Lite
Findings: 2 High severity · 1 Medium severity

Open (3)
What changed in this PR

Refactors device-state collection into a shared tracker used by sync UI, troubleshooting, logout handling, and session payload generation.

Changes:

  • Replaces SyncableCounts with DeviceStateDataTracker and DeviceDataState.
  • Adds reactive event scope counting and migrates consumers.
  • Updates troubleshooting UI and related tests.
File Reviewed change
infra/​sync/​src/​test/​java/​com/​simprints/​infra/​sync/​usecase/​ObserveSyncableCountsUseCaseTest.kt Removes obsolete tests
infra/​sync/​src/​test/​java/​com/​simprints/​infra/​sync/​devicestate/​internal/​ObserveSamplesToUploadCountUseCaseTest.kt Updates package and tests
infra/​sync/​src/​test/​java/​com/​simprints/​infra/​sync/​devicestate/​internal/​ObserveEnrolmentRecordsCountUseCaseTest.kt Updates package and tests
infra/​sync/​src/​test/​java/​com/​simprints/​infra/​sync/​devicestate/​DeviceStateDataTrackerImplTest.kt Adds tracker coverage
infra/​sync/​src/​test/​java/​com/​simprints/​infra/​sync/​config/​usecase/​HandleProjectStateUseCaseTest.kt Tests tracker-based logout decisions
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​usecase/​ObserveSyncableCountsUseCase.kt Removes obsolete use case
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​SyncModule.kt Binds the new tracker
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​SyncableCounts.kt Removes obsolete model
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​devicestate/​internal/​ObserveSamplesToUploadCountUseCase.kt Relocates sample counting
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​devicestate/​internal/​ObserveEnrolmentRecordsCountUseCase.kt Relocates enrolment counting
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​devicestate/​DeviceStateDataTrackerImpl.kt Implements state aggregation
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​devicestate/​DeviceStateDataTracker.kt Defines tracker API
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​devicestate/​DeviceDataState.kt Defines aggregated state
infra/​sync/​src/​main/​java/​com/​simprints/​infra/​sync/​config/​usecase/​HandleProjectStateUseCase.kt Uses tracker for logout decisions
infra/​events/​src/​test/​java/​com/​simprints/​infra/​events/​event/​local/​SessionScopeRoomDaoTest.kt Tests scope count queries
infra/​events/​src/​test/​java/​com/​simprints/​infra/​events/​event/​local/​EventLocalDataSourceTest.kt Tests count mapping and recovery
infra/​events/​src/​main/​java/​com/​simprints/​infra/​events/​EventRepositoryImpl.kt Exposes scope counts
infra/​events/​src/​main/​java/​com/​simprints/​infra/​events/​EventRepository.kt Adds scope-count API
infra/​events/​src/​main/​java/​com/​simprints/​infra/​events/​event/​local/​SessionScopeRoomDao.kt Adds grouped count query
infra/​events/​src/​main/​java/​com/​simprints/​infra/​events/​event/​local/​models/​DbScopeTypeCount.kt Adds Room projection
infra/​events/​src/​main/​java/​com/​simprints/​infra/​events/​event/​local/​EventLocalDataSource.kt Maps and zero-fills counts
feature/​troubleshooting/​src/​test/​java/​com/​simprints/​feature/​troubleshooting/​overview/​usecase/​CollectDeviceDataStateUseCaseTest.kt Tests state formatting
feature/​troubleshooting/​src/​test/​java/​com/​simprints/​feature/​troubleshooting/​overview/​OverviewViewModelTest.kt Tests state collection
feature/​troubleshooting/​src/​main/​res/​layout/​fragment_troubleshooting_overview.xml Adds device-data section
feature/​troubleshooting/​src/​main/​java/​com/​simprints/​feature/​troubleshooting/​overview/​usecase/​CollectDeviceDataStateUseCase.kt Formats device state
feature/​troubleshooting/​src/​main/​java/​com/​simprints/​feature/​troubleshooting/​overview/​OverviewViewModel.kt Loads device state
feature/​troubleshooting/​src/​main/​java/​com/​simprints/​feature/​troubleshooting/​overview/​OverviewFragment.kt Displays device state
feature/​troubleshooting/​build.gradle.kts Adds sync dependency
feature/​login-check/​src/​test/​java/​com/​simprints/​feature/​logincheck/​usecases/​UpdateSessionScopePayloadUseCaseTest.kt Updates payload tests
feature/​login-check/​src/​main/​java/​com/​simprints/​feature/​logincheck/​usecases/​UpdateSessionScopePayloadUseCase.kt Uses tracker counts
feature/​dashboard/​src/​test/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​ObserveSyncInfoUseCaseTest.kt Updates sync-info tests
feature/​dashboard/​src/​test/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​internal/​GetSyncInfoSectionRecordsUseCaseTest.kt Tests record counters
feature/​dashboard/​src/​test/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​internal/​GetSyncInfoSectionImagesUseCaseTest.kt Tests image counters
feature/​dashboard/​src/​test/​java/​com/​simprints/​feature/​dashboard/​settings/​about/​AboutViewModelTest.kt Tests logout checks
feature/​dashboard/​src/​main/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​ObserveSyncInfoUseCase.kt Combines tracker and down-sync state
feature/​dashboard/​src/​main/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​internal/​GetSyncInfoSectionRecordsUseCase.kt Reads device-state counters
feature/​dashboard/​src/​main/​java/​com/​simprints/​feature/​dashboard/​settings/​syncinfo/​usecase/​internal/​GetSyncInfoSectionImagesUseCase.kt Reads sample counters
feature/​dashboard/​src/​main/​java/​com/​simprints/​feature/​dashboard/​settings/​about/​AboutViewModel.kt Uses tracker for logout checks

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comment thread infra/sync/src/main/java/com/simprints/infra/sync/ImageSyncTimestampProvider.kt Outdated

Copilot AI left a comment

Copy link
Copy Markdown

@luhmirin-s
luhmirin-s force-pushed the feature/MS-1537-hearthbeat-request branch from a5f9db1 to a50be41 Compare September 30, 2026 09:09
@luhmirin-s
luhmirin-s marked this pull request as ready for review September 30, 2026 09:21
@sonarqubecloud

Copy link
Copy Markdown

@luhmirin-s luhmirin-s changed the title [WIP] MS-1537 Bonus refactoring - device state tracker MS-1537 Bonus refactoring - device state tracker Sep 30, 2026
@luhmirin-s
luhmirin-s requested review from a team, BurningAXE, TristramN, alex-vt and meladRaouf and removed request for a team September 30, 2026 12:22

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants