Skip to content

Store RFC: Improving Sync #697

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 2 commits into
base: main
Choose a base branch
from
Open

Store RFC: Improving Sync #697

wants to merge 2 commits into from

Conversation

matt-ramotar
Copy link
Collaborator

See: #677, #685

Signed-off-by: Matt Ramotar <[email protected]>
Copy link

codecov bot commented Feb 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 75.43%. Comparing base (2aa3213) to head (8c5c75c).
Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #697   +/-   ##
=======================================
  Coverage   75.43%   75.43%           
=======================================
  Files          38       38           
  Lines         920      920           
  Branches      168      168           
=======================================
  Hits          694      694           
  Misses        142      142           
  Partials       84       84           
🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@blakelee blakelee left a comment

Choose a reason for hiding this comment

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

I took a look at this. I had a couple questions:

  1. Is Meeseeks one of the StoreX extensions coming in the future? There were a lot of references and I inferred that it would be one of them.
  2. Regarding partial failure handling: This is a new concept for me. Is the idea that some items may fail to update and we need to gracefully handle that case, whereas others may succeed so you can handle those as usual?
  3. I imagine a one case could look like this: You have a fetcher that's a stream to the server, new items are constantly coming in, based on any updates that may or may not have happened, the conflict resolution strategy will take care of how to handle the updates.

Thanks a lot for writing this up. The timeline at the bottom is promising too. I think this piece of the puzzle will help mobile developers solve a problem that many of them have but don't have the resources to create for themselves.

What would you like from us the consumers of Store?

@matt-ramotar
Copy link
Collaborator Author

@blakelee Hey Blake, thanks for taking a look.

  1. Yes, Meeseeks is a library I'm working on now. We need a KMP scheduling solution to help Store automatically retry unsynced operations in the background.
  2. Yes, exactly. "Partial failure handling" becomes important in scenarios where multiple items are batched together in a single operation. For instance, you might request deleteMany for five items, but only three succeed while two fail. Store will need to provide a clear way for developers to detect and handle that situation - whether that means retrying just the failed items, rolling back changes, or something else defined by the developer.
  3. That’s definitely a key scenario we’re targeting. When Fetcher returns new or updated items in real time (or near real time), Store’s conflict resolution policy will determine how to merge those updates with what is currently in the local cache or SOT. By providing hooks for custom conflict resolution, developers can decide how to handle (e.g., last write wins, field by field merge).
  4. Right now, we're hoping the community can:
    • Share real-world scenarios, especially complex/unique conflict resolution needs (understanding this will help us refine designs)
    • Provide feedback on the RFC itself
    • Contribute to any of the sub-projects (e.g., conflict resolution, Meeseeks, partial failure handling)


The overarching goal of this RFC is to enhance Store5’s synchronization features without introducing breaking changes. In particular:

1. **Synchronization Resilience**: Automated retries and background scheduling using the `Meeseeks` library (a KMP task scheduling library influenced by [WorkManager](https://developer.android.com/reference/androidx/work/WorkManager) and [BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler)).

Choose a reason for hiding this comment

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

I couldn’t find the meeseeks library

Choose a reason for hiding this comment

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

Ahhh, it’s described below

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Expanded on Meeseeks with links to the repo and docs 👍🏽

- **Reviewers**: _TBD_
- **Started**: February 22, 2025

## Introduction

Choose a reason for hiding this comment

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

I was expecting to see a discussion of CRDTs
https://crdt.tech/

Choose a reason for hiding this comment

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

Or perhaps Automerge which is a pretty rad implementation of CRDT ideas

Choose a reason for hiding this comment

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

Requiring Store5 to store CRDTs would limit the types that users can leverage. It seems like the best place for them would be in the user's own conflict resolution wiring.


Store5 specifically introduced the `MutableStore` API to unify local and remote data synchronization. It provides mechanisms for create, update, and delete operations. However, we’ve identified critical gaps around resilience (automated retry, robust background sync) and deletion handling (both local and server-initiated removals). Along with these, we also need customizable conflict resolution strategies to better address real-world complexities.

The overarching goal of this RFC is to enhance Store5’s synchronization features without introducing breaking changes. In particular:
Copy link
Member

Choose a reason for hiding this comment

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

This implies there would be some changes proposed if we were interested in breaking changes, that aren't called out here. Is there anything else in the sync category, or something we would have proposed differently here, if that was on the table and we'd want to discuss those with a major version bump at some point in the future?


5. **Backward Compatibility**

Not willing to break existing usage. Not all developers need advanced sync.
Copy link
Member

Choose a reason for hiding this comment

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

What does advanced sync entail that we're intentionally leaving out?

Signed-off-by: Matt Ramotar <[email protected]>

The overarching goal of this RFC is to enhance Store5’s synchronization features without introducing breaking changes. In particular:

1. **Synchronization Resilience**: Automated retries and background scheduling using the [Meeseeks](https://docs.meeseeks.mattramotar.dev/) library (a KMP task scheduling library influenced by [WorkManager](https://developer.android.com/reference/androidx/work/WorkManager) and [BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler)).

Choose a reason for hiding this comment

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

There should also be a way to trigger it manually. On iOS in aprticular BGTaskScheduler is not very configurable -- it is basically up to the OS when to call the task, and iOS provides very few if any guarantees on timing.

The system decides the best time to launch your background task, and provides your app up to 30 seconds of background runtime.

(reference)

Alternative strategies include things like waking the app with a background push and triggering sync from there, but this requires the manual API.

- **Reviewers**: _TBD_
- **Started**: February 22, 2025

## Introduction

Choose a reason for hiding this comment

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

Requiring Store5 to store CRDTs would limit the types that users can leverage. It seems like the best place for them would be in the user's own conflict resolution wiring.


We have the building blocks for robust sync ([MutableStore](https://store.mobilenativefoundation.org/docs/concepts/store5/mutable-store), [Bookkeeper](https://store.mobilenativefoundation.org/docs/concepts/store5/bookkeeper), [Updater](https://store.mobilenativefoundation.org/docs/concepts/store5/updater), [SourceOfTruth](https://store.mobilenativefoundation.org/docs/concepts/store5/source-of-truth)). But we need to tighten up deletion support, add background sync scheduling, and clarify conflict resolution flows.

## Considerations

Choose a reason for hiding this comment

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

Should there be a consideration here for synchronization failure handling? Say an item is added to the SoT. When this item syncs to the server, there are two possibilities: 1) the item is invalid in some way, and rejected by the server (think 400 Bad Request), or 2) the item fails to sync due to some temporary problem e.g. network error, backend component down, etc. (think 502 Bad Gateway).

This also implies some kind of maximum retries counter -- sometimes the server does not correctly identify a bad request and instead returns a 500 Server Error. But the error is due to a problem in the request, so we can't keep retrying it forever.

These failed items should be stored in a way that the problem can optionally be surfaced to a user for correction, and updating the item in the local SoT.

I wrote this in #677 :

Lastly, some values may never sync to the server because it is malformed or violates server preconditions in some way. Part of the API should allow inspecting the failures for items that have failed to sync and invalidating them i.e. clearing or setting some relevant state in bookkeeper and moving them to some kind of "failed" status in the source of truth.


We have the building blocks for robust sync ([MutableStore](https://store.mobilenativefoundation.org/docs/concepts/store5/mutable-store), [Bookkeeper](https://store.mobilenativefoundation.org/docs/concepts/store5/bookkeeper), [Updater](https://store.mobilenativefoundation.org/docs/concepts/store5/updater), [SourceOfTruth](https://store.mobilenativefoundation.org/docs/concepts/store5/source-of-truth)). But we need to tighten up deletion support, add background sync scheduling, and clarify conflict resolution flows.

## Considerations

Choose a reason for hiding this comment

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

Another consideration is the ability to retrieve the sync state of items. I wrote this in #677 :

Related to this, I would like a nice API to retrieve information about failed syncs. This could be used to display information to the user like "5 items have not yet synced to the server"

I'm not sure if Bookkeeper already provides this capability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 Triage
Development

Successfully merging this pull request may close these issues.

8 participants