Skip to content
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

feat: soil change tracking #2364

Merged
merged 8 commits into from
Oct 24, 2024
Merged

feat: soil change tracking #2364

merged 8 commits into from
Oct 24, 2024

Conversation

tm-ruxandra
Copy link
Contributor

Description

Add a data model to track changes relevant to the sync system. Entities have change records containing a revision ID and information about the last change and last successful sync. The Soil ID slice tracks changes for soil data by updating the change records when mutations occur and marking them as synced when user data is loaded from the server. The number of un-synced sites is exposed through the sync button component for diagnostic purposes.

Also adds a basic system for patching data loaded from disk during startup -- ultimately we will want this to work by merging the slices' default initial states with the states saved to mmkv, however circular app dependencies prevented this and so we should revisit it as follow-on work once the main offline feature is done.

Checklist

  • Corresponding issue has been opened
  • New tests added

Related Issues

Fixes #2278

Verification steps

Make changes to soil data and observe that the number of unsynced sites changes appropriately. Reload the user's data and observe that changes are marked as synced.

Copy link
Member

@shrouxm shrouxm left a comment

Choose a reason for hiding this comment

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

LGTM!

a few take it or leave it comments mostly about documentation/code organization. i feel most strongly about the one asking for a write up how the data flow is supposed to work, but i might be misremembering what scenarios this code is supposed to handle in which case it's less relevant

Comment on lines 43 to 47
export const patchPersistedReduxState = (state?: Partial<AppState>) => {
if (state) {
merge(state, {soilId: {soilChanges: {}}});
}
};
Copy link
Member

Choose a reason for hiding this comment

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

suggestions:

  • should we use this as part of the implementation of loadPersistedReduxState rather than exporting and relying on clients to remember to call it?
  • should we use immutable logic here instead of mutating the state object? (i think if you import merge from 'lodash/fp' instead of 'lodash' you will get this behavior)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. I don't think that's necessary. I'd rather be able to test the load/save functionality in isolation and also test this in isolation. I don't think the issue of clients "remembering" to call this method is substantial since there is only one client (the app at startup).
  2. Good idea, I'll make that change.

Comment on lines +67 to +68
export const markAllChanged = <T>(
records: ChangeRecords<T>,
Copy link
Member

Choose a reason for hiding this comment

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

question: thoughts on using Draft<ChangeRecords<T>>? implicitly that is what is happening when this method gets called via the soil ID slice, so it seems nice to be explicit about it (since it would probably be a bug if we were using this method on something that is not a draft). i'm not sure whether that would make the test code more awkward though, and don't feel too strongly about it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand the principle of being more explicit about when we're operating on intermediate Redux state vs. immutable data. I'm hesitant to engineer a potentially-complex approach to that right now (as you note it could have consequences for testing) but in a subsequent PR I'd be open to it, once we fully understand how this code is used in a well-tested push implementation.

Comment on lines 77 to 93
export const markChanged = <T>(
records: ChangeRecords<T>,
id: string,
at: ChangeTimestamp,
) => {
const prevRecord = getChange(records, id);
const prevRevisionId = getRevisionId(prevRecord);
const revisionId = nextRevisionId(prevRevisionId);
records[id] = {
revisionId: revisionId,
lastModifiedAt: at,

lastSyncedRevisionId: prevRecord?.lastSyncedRevisionId,
lastSyncedData: prevRecord?.lastSyncedData,
lastSyncedAt: prevRecord?.lastSyncedAt,
};
};
Copy link
Member

Choose a reason for hiding this comment

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

question: am i remembering right that this version is meant to handle cases where the client makes further changes while a push or pull is in flight? i'm having trouble remembering the logic of how/in what order these methods are going to be called to handle that scenario (or am maybe misremembering whether this version is supposed to handle that scenario) and am wondering if you could write it up in a comment somewhere in this file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(Assuming that by "this version" you mean the revision ID)

So there is already a comment but I can rewrite it for better clarity. Yes, the intended use of revision IDs is to handle situations where data gets changed while a sync is in progress so that we do not overwrite user changes with the results of a stale operation.

@tm-ruxandra tm-ruxandra merged commit 7693518 into main Oct 24, 2024
10 checks passed
@tm-ruxandra tm-ruxandra deleted the feat/soil-change-tracking branch October 24, 2024 21:28
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.

[Offline] Add basic change-tracking to soil data in Soil ID redux slice
2 participants