Skip to content

feat: local vs server sync (M2-10227)#1062

Open
sricharan-varanasi wants to merge 37 commits intodevfrom
M2-10227-local-vs-server-sync
Open

feat: local vs server sync (M2-10227)#1062
sricharan-varanasi wants to merge 37 commits intodevfrom
M2-10227-local-vs-server-sync

Conversation

@sricharan-varanasi
Copy link
Copy Markdown
Contributor

@sricharan-varanasi sricharan-varanasi commented Jan 27, 2026

  • Tests for the changes have been added
  • Related documentation has been added / updated
  • OSS packages added to Curious open source credit page

📝 Description

🔗 Jira Ticket M2-10227
🔗 Jira Ticket M2-10405

Implements cross-device flow completion detection and sync improvements to handle users resuming flows across multiple devices.

Changes include:

Backend Enhancement:

  • Added getAppletCompletedEntities API endpoint to fetch completion data for a single applet (instead of all applets)

New Services & Hooks:

  • Created TargetedProgressSyncService - syncs completion data for one specific applet without triggering full applet refresh
  • Added useTargetedSync React hook - provides easy integration with syncApplet(appletId) function and isRefreshing state

Screen Updates:

  • InProgressActivityScreen - replaced full refresh with targeted sync when resuming activities

  • ActivityListScreen - replaced full refresh with targeted sync after completing activities

  • Added cross-device completion check when resuming flows - detects if a flow was completed on another device and blocks resumption with user notification

  • Enhanced flow state reconstruction from server data with proper activity order tracking

  • Improved sync logic for in-progress flows to maintain correct flow state across devices

  • Added conflict resolution for completed vs in-progress flow states

  • Extended flow state tracking to include remainingActivityOrders for accurate flow position reconstruction

🪤 Peer Testing

Test cross-device flow completion:

  1. Start a flow on Device A and complete the first activity

  2. On Device B, pull to refresh the applet list

  3. Tap Resume on the same flow

  4. On Device A, complete the entire flow

  5. On Device B, tap Next to proceed in the flow

    Expected outcome: Alert appears stating "This flow was completed on another device" and the view refreshes to show the completed state

Test flow reconstruction after sync:

  1. Start a multi-activity flow on Device A and complete 2 activities

  2. Force close the app on Device A

  3. On Device B, resume the flow from the beginning

    Expected outcome: Flow resumes from activity 3 (where Device A left off), not from the beginning

✏️ Notes

  • Cleaned up debug logging statements added during development
  • Related to M2-10226 (fetch in-progress flows from server on resume)

divbzero and others added 23 commits January 5, 2026 08:57
- Update CompletedEntityDto to make localEndDate and localEndTime nullable to match DB schema
When syncing in-progress flows from the server, reconstruct the FlowState
with the correct pipeline and step, then save it to local storage. This
ensures that when the user clicks Resume, the flow continues from the
correct activity instead of starting from the beginning.
@sricharan-varanasi sricharan-varanasi marked this pull request as draft January 27, 2026 05:07
@sricharan-varanasi sricharan-varanasi force-pushed the M2-10227-local-vs-server-sync branch from d830445 to aa19cff Compare January 27, 2026 19:32
@sricharan-varanasi sricharan-varanasi marked this pull request as ready for review January 27, 2026 19:37
Copy link
Copy Markdown
Contributor

@divbzero divbzero left a comment

Choose a reason for hiding this comment

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

Just a few minor questions. Otherwise looks good!

@sricharan-varanasi sricharan-varanasi force-pushed the M2-10227-local-vs-server-sync branch from 54d648e to c2e03aa Compare January 28, 2026 18:42
- Add getAppletCompletedEntities API method to IEventsService
- Implement single-applet completions endpoint in eventsService
- Create TargetedProgressSyncService for targeted sync without full refresh
- Fetches only one applet's completions instead of all applets
- Use useTargetedSync hook instead of useRefreshMutation
- Remove loading spinner (sync is fast and non-blocking)
- Keep AppletsRefresh for manual pull-to-refresh
…reen

- Use useTargetedSync hook instead of useRefreshMutation
- Add isRefreshing state to useTargetedSync for loading feedback
- Keep loading spinner for safety during sync
- Enhanced AppletsRefresh to sync applet data before rescheduling notifications
  when appletId is provided
- Modified ActivityListScreen to pass appletId to AppletsRefresh for targeted
  data sync on pull-to-refresh
- Added query invalidation in Intermediate.tsx and Finish.tsx to automatically
  update activity list after completing activities
- Add subjectId to AppletRespondentMetaDto to access logged-in user's ID
- Make CompletedEntityDto.targetSubjectId nullable to match web's type definition
- Add QueryDataUtils.getRespondentMeta() to access cached respondent data
- Normalize targetSubjectId in ProgressSyncService: if it equals the logged-in
  user's subjectId, convert it to null before creating storage keys
@sricharan-varanasi sricharan-varanasi force-pushed the M2-10227-local-vs-server-sync branch from e0f600a to bf45880 Compare February 5, 2026 04:29
@sricharan-varanasi sricharan-varanasi force-pushed the M2-10227-local-vs-server-sync branch from 6009c8c to 538640f Compare February 10, 2026 15:31
- Revert slice.ts to pre-removal version (already has web-matching submitId logic)
- Add matching submitId comparison logic to ProgressSyncService.reconstructFlowState
- Both layers now use same skip logic to stay in sync:
  - Same submitId: keep furthest progress in this submission
  - Different submitId: keep furthest in-progress OR most recent completed
Copy link
Copy Markdown
Contributor

@divbzero divbzero left a comment

Choose a reason for hiding this comment

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

The updated logic in src/entities/applet/model/services/ProgressSyncService.ts and src/entities/applet/model/slice.ts looks good. Thank you @sricharan-varanasi!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants