Skip to content

Commit c5fee94

Browse files
authored
Add sync pause and resume (#42)
1 parent 1559d25 commit c5fee94

File tree

8 files changed

+593
-13
lines changed

8 files changed

+593
-13
lines changed

CLAUDE.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ _watcher.EnableRaisingEvents = true;
293293
| Gap | Impact | Status |
294294
|-----|--------|--------|
295295
| No selective folder sync API | Can't sync single folders on demand | Planned: `SyncFolderAsync()`, `SyncFilesAsync()` |
296-
| No pause/resume | Long syncs can't be paused | Planned: `PauseAsync()`, `ResumeAsync()` |
297296
| No incremental change notification | FileSystemWatcher triggers full scan | Planned: `NotifyLocalChangeAsync()` |
298297
| Single-threaded engine | One sync at a time per instance | By design - create separate instances if needed |
299298
| OCIS TUS not implemented | Falls back to generic upload | Planned for v1.0 |
@@ -304,6 +303,7 @@ _watcher.EnableRaisingEvents = true;
304303
|---------|----------------|
305304
| Bandwidth throttling | `SyncOptions.MaxBytesPerSecond` - limits transfer rate |
306305
| Virtual file awareness | `SyncOptions.VirtualFileCallback` - hook for Windows Cloud Files API integration |
306+
| Pause/Resume sync | `PauseAsync()` / `ResumeAsync()` - gracefully pause and resume long-running syncs |
307307

308308
### Required SharpSync API Additions (v1.0)
309309

@@ -318,8 +318,7 @@ These APIs are required for v1.0 release to support Nimbus desktop client:
318318
4. OCIS TUS protocol implementation (`WebDavStorage.cs:547` currently falls back)
319319

320320
**Sync Control:**
321-
5. `PauseAsync()` / `ResumeAsync()` - Pause and resume long-running syncs
322-
6. `GetPendingOperationsAsync()` - Inspect sync queue for UI display
321+
5. `GetPendingOperationsAsync()` - Inspect sync queue for UI display
323322

324323
**Progress & History:**
325324
7. Per-file progress events (currently only per-sync-operation)
@@ -331,6 +330,8 @@ These APIs are required for v1.0 release to support Nimbus desktop client:
331330
- `SyncOptions.CreateVirtualFilePlaceholders` - Enable/disable virtual file placeholder creation
332331
- `VirtualFileState` enum - Track placeholder state (None, Placeholder, Hydrated, Partial)
333332
- `SyncPlanAction.WillCreateVirtualPlaceholder` - Preview which downloads will create placeholders
333+
- `PauseAsync()` / `ResumeAsync()` - Gracefully pause and resume long-running syncs
334+
- `IsPaused` property and `SyncEngineState` enum - Track engine state (Idle, Running, Paused)
334335

335336
### API Readiness Score for Nimbus
336337

@@ -344,10 +345,10 @@ These APIs are required for v1.0 release to support Nimbus desktop client:
344345
| UI binding (events) | 9/10 | Excellent progress/conflict events |
345346
| Conflict resolution | 9/10 | Rich analysis, extensible callbacks |
346347
| Selective sync | 4/10 | Filter-only, no folder/file API |
347-
| Pause/Resume | 2/10 | Not implemented |
348-
| Desktop integration hooks | 8/10 | Virtual file callback, bandwidth throttling implemented |
348+
| Pause/Resume | 10/10 | Fully implemented with graceful pause points |
349+
| Desktop integration hooks | 9/10 | Virtual file callback, bandwidth throttling, pause/resume |
349350

350-
**Current Overall: 7.25/10** - Solid foundation, key desktop hooks now available
351+
**Current Overall: 8.4/10** - Strong foundation with key desktop features implemented
351352

352353
**Target for v1.0: 9.5/10** - All gaps resolved, ready for Nimbus development
353354

@@ -501,6 +502,7 @@ The core library is production-ready, but several critical items must be address
501502
- ✅ Bandwidth throttling (`SyncOptions.MaxBytesPerSecond`)
502503
- ✅ Virtual file placeholder support (`SyncOptions.VirtualFileCallback`) for Windows Cloud Files API
503504
- ✅ High-performance logging with `Microsoft.Extensions.Logging.Abstractions`
505+
- ✅ Pause/Resume sync (`PauseAsync()` / `ResumeAsync()`) with graceful pause points
504506

505507
**🚧 Required for v1.0 Release**
506508

@@ -517,7 +519,7 @@ Desktop Client APIs (for Nimbus):
517519
- [ ] `NotifyLocalChangeAsync(string path, ChangeType type)` - Accept FileSystemWatcher events for incremental sync
518520
- [ ] OCIS TUS protocol implementation (currently falls back to generic upload at `WebDavStorage.cs:547`)
519521
- [x] `SyncOptions.MaxBytesPerSecond` - Built-in bandwidth throttling ✅
520-
- [ ] `PauseAsync()` / `ResumeAsync()` - Pause and resume long-running syncs
522+
- [x] `PauseAsync()` / `ResumeAsync()` - Pause and resume long-running syncs
521523
- [ ] `GetPendingOperationsAsync()` - Inspect sync queue for UI display
522524
- [ ] Per-file progress events (currently only per-sync-operation)
523525
- [x] `SyncOptions.VirtualFileCallback` - Hook for virtual file systems (Windows Cloud Files API) ✅

src/SharpSync/Core/ISyncEngine.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ public interface ISyncEngine: IDisposable {
1919
/// </summary>
2020
bool IsSynchronizing { get; }
2121

22+
/// <summary>
23+
/// Gets whether the engine is currently paused
24+
/// </summary>
25+
bool IsPaused { get; }
26+
27+
/// <summary>
28+
/// Gets the current state of the sync engine
29+
/// </summary>
30+
SyncEngineState State { get; }
31+
2232
/// <summary>
2333
/// Synchronizes files between local and remote storage
2434
/// </summary>
@@ -51,4 +61,38 @@ public interface ISyncEngine: IDisposable {
5161
/// Resets all sync state (forces full rescan)
5262
/// </summary>
5363
Task ResetSyncStateAsync(CancellationToken cancellationToken = default);
64+
65+
/// <summary>
66+
/// Pauses the current synchronization operation
67+
/// </summary>
68+
/// <remarks>
69+
/// <para>
70+
/// The pause is graceful - the engine will complete the current file operation
71+
/// before entering the paused state. This ensures no partial file transfers occur.
72+
/// </para>
73+
/// <para>
74+
/// If no synchronization is in progress, this method returns immediately.
75+
/// </para>
76+
/// <para>
77+
/// While paused, the <see cref="ProgressChanged"/> event will fire with
78+
/// <see cref="SyncOperation.Paused"/> to indicate the paused state.
79+
/// </para>
80+
/// </remarks>
81+
/// <returns>A task that completes when the engine has entered the paused state</returns>
82+
Task PauseAsync();
83+
84+
/// <summary>
85+
/// Resumes a paused synchronization operation
86+
/// </summary>
87+
/// <remarks>
88+
/// <para>
89+
/// If the engine is not paused, this method returns immediately.
90+
/// </para>
91+
/// <para>
92+
/// After resuming, synchronization continues from where it was paused,
93+
/// processing any remaining files in the sync queue.
94+
/// </para>
95+
/// </remarks>
96+
/// <returns>A task that completes when the engine has resumed</returns>
97+
Task ResumeAsync();
5498
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace Oire.SharpSync.Core;
2+
3+
/// <summary>
4+
/// Represents the current state of the sync engine
5+
/// </summary>
6+
public enum SyncEngineState {
7+
/// <summary>
8+
/// The engine is idle and not performing any sync operation
9+
/// </summary>
10+
Idle,
11+
12+
/// <summary>
13+
/// The engine is actively synchronizing files
14+
/// </summary>
15+
Running,
16+
17+
/// <summary>
18+
/// The engine is paused and waiting to be resumed
19+
/// </summary>
20+
Paused
21+
}

src/SharpSync/Core/SyncOperation.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,10 @@ public enum SyncOperation {
3737
/// <summary>
3838
/// Resolving a synchronization conflict
3939
/// </summary>
40-
ResolvingConflict
40+
ResolvingConflict,
41+
42+
/// <summary>
43+
/// The sync operation is paused
44+
/// </summary>
45+
Paused
4146
}

src/SharpSync/Core/SyncProgress.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ public record SyncProgress {
4343
/// Gets whether the operation has been cancelled
4444
/// </summary>
4545
public bool IsCancelled { get; init; }
46+
47+
/// <summary>
48+
/// Gets whether the operation is currently paused
49+
/// </summary>
50+
public bool IsPaused { get; init; }
4651
}

src/SharpSync/Logging/LogMessages.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,28 @@ internal static partial class LogMessages {
4141
Level = LogLevel.Warning,
4242
Message = "Virtual file callback failed for {FilePath}")]
4343
public static partial void VirtualFileCallbackError(this ILogger logger, Exception ex, string filePath);
44+
45+
[LoggerMessage(
46+
EventId = 7,
47+
Level = LogLevel.Information,
48+
Message = "Sync pause requested, waiting for current operation to complete")]
49+
public static partial void SyncPausing(this ILogger logger);
50+
51+
[LoggerMessage(
52+
EventId = 8,
53+
Level = LogLevel.Information,
54+
Message = "Sync paused")]
55+
public static partial void SyncPaused(this ILogger logger);
56+
57+
[LoggerMessage(
58+
EventId = 9,
59+
Level = LogLevel.Information,
60+
Message = "Sync resume requested")]
61+
public static partial void SyncResuming(this ILogger logger);
62+
63+
[LoggerMessage(
64+
EventId = 10,
65+
Level = LogLevel.Information,
66+
Message = "Sync resumed")]
67+
public static partial void SyncResumed(this ILogger logger);
4468
}

0 commit comments

Comments
 (0)