feat(recovery): crash recovery and sync resumption (#39)#51
Merged
Conversation
Merge GetFirstFolderPageAsync/GetNextFolderPageAsync into single GetFolderPageAsync(string? nextLink), collapse two GetFoldersFromPagesAsync overloads into one nullable-accumulator method, inline GetDriveFoldersAsync, drop Children() helper, and add GraphClient type alias. Codify the three emerging patterns in c-sharp-code-style.md (using alias, nullable accumulator over overload pair, inline single-use wrapper) and replace the Getting root folders prose in onedrive-graph.md with concrete code examples from the refactored GraphService. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests reference ISyncRepository.GetInterruptedJobsAsync/ResetInterruptedJobsAsync, ISyncRecoveryService, InterruptedSyncInfo, and WorkspaceViewModel recovery props — none of which exist yet. Compile errors: 6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ISyncRecoveryService / SyncRecoveryService to detect interrupted syncs (Status=="Running" jobs surviving restart) and report whether delta-token-based resumption is possible - Add InterruptedSyncInfo record (AccountId, AccountName, CanResume, Message) - Extend ISyncRepository with GetInterruptedJobsAsync and ResetInterruptedJobsAsync; implement in SyncRepository - Expose HasInterruptedSyncs on WorkspaceViewModel; detect on startup via LoadPersistedAccountsAsync - Register ISyncRecoveryService as Transient in App.axaml.cs - Add implicit conversion operators to Result<TResult,TError> so return sites can use plain values; clean up all verbose Ok/Fail wrapping across repositories, services, and Graph layer - Add integration tests for interrupted-job repository methods (8 tests) - Add unit tests for SyncRecoveryService (8 tests) Closes #39 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jbarden
approved these changes
May 28, 2026
jbarden
left a comment
There was a problem hiding this comment.
reviewed and updated locally before PR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SyncRepository.GetInterruptedJobsAsyncfinds jobs withStatus == "Running"that survived a crash/restart;WorkspaceViewModel.LoadPersistedAccountsAsynccallsISyncRecoveryService.DetectAsyncand setsHasInterruptedSyncsSyncRecoveryServicechecksDriveStateEntity.DeltaLink; non-empty means delta token was preserved and incremental sync can continue;CanResumeflag surfaced viaInterruptedSyncInfoInterruptedSyncInfo.Messageprovides a non-technical explanation ("Sync resumed from last checkpoint." or "Sync interrupted. No checkpoint found — a full sync will run on next attempt.")Result<T,E>: AddedTResult → ResultandTError → Resultoperators; cleaned all verbosenew Ok<T,E>(v)/new Fail<T,E>(e)return sites across repositories, services, and Graph layerTest plan
dotnet build— 0 errors, 0 warningsGivenASyncRecoveryServicetests + 2 newWorkspaceViewModelrecovery tests)GivenASyncRepositoryInterruptedJobstests)Closes #39
🤖 Generated with Claude Code