diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index a98a0e1..07f9959 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -36,6 +36,8 @@ jobs:
run: |
echo "=== Starting test services with docker-compose ==="
docker compose -f docker-compose.test.yml up -d
+ env:
+ LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
- name: Wait for services to be ready
if: matrix.os == 'ubuntu-latest'
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
index 08a0bf7..841c9fb 100644
--- a/docker-compose.test.yml
+++ b/docker-compose.test.yml
@@ -36,9 +36,7 @@ services:
ports:
- "4566:4566"
environment:
- SERVICES: s3
- DEBUG: 0
- EDGE_PORT: 4566
+ LOCALSTACK_AUTH_TOKEN: ${LOCALSTACK_AUTH_TOKEN:-}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4566/_localstack/health"]
interval: 15s
diff --git a/src/SharpSync/SharpSync.csproj b/src/SharpSync/SharpSync.csproj
index 7ac6cdc..cbbd6ac 100644
--- a/src/SharpSync/SharpSync.csproj
+++ b/src/SharpSync/SharpSync.csproj
@@ -52,7 +52,7 @@
-
+
diff --git a/src/SharpSync/Sync/SyncEngine.cs b/src/SharpSync/Sync/SyncEngine.cs
index b067f65..33d1e8b 100644
--- a/src/SharpSync/Sync/SyncEngine.cs
+++ b/src/SharpSync/Sync/SyncEngine.cs
@@ -752,6 +752,9 @@ private async Task ProcessChangesAsync(ChangeSet changes, SyncOptions? options,
await ProcessPhase1_DirectoriesAndSmallFilesAsync(actionGroups, threadSafeResult, progressCounter, totalChanges, cancellationToken).ConfigureAwait(false);
await ProcessPhase2_LargeFilesAsync(actionGroups, threadSafeResult, progressCounter, totalChanges, cancellationToken).ConfigureAwait(false);
await ProcessPhase3_DeletesAndConflictsAsync(actionGroups, threadSafeResult, progressCounter, totalChanges, cancellationToken).ConfigureAwait(false);
+
+ // Write final atomic counter values to the result
+ threadSafeResult.Flush();
}
///
diff --git a/src/SharpSync/Sync/ThreadSafeSyncResult.cs b/src/SharpSync/Sync/ThreadSafeSyncResult.cs
index 23bc585..d477f45 100644
--- a/src/SharpSync/Sync/ThreadSafeSyncResult.cs
+++ b/src/SharpSync/Sync/ThreadSafeSyncResult.cs
@@ -3,7 +3,9 @@
namespace Oire.SharpSync.Sync;
///
-/// Thread-safe wrapper for SyncResult counters
+/// Thread-safe wrapper for SyncResult counters.
+/// Call after all parallel processing completes
+/// to write the final values to the underlying .
///
internal sealed class ThreadSafeSyncResult {
private readonly SyncResult _result;
@@ -16,23 +18,22 @@ public ThreadSafeSyncResult(SyncResult result) {
_result = result;
}
- public void IncrementFilesSynchronized() {
- var newValue = Interlocked.Increment(ref _filesSynchronized);
- _result.FilesSynchronized = newValue;
- }
+ public void IncrementFilesSynchronized() => Interlocked.Increment(ref _filesSynchronized);
- public void IncrementFilesSkipped() {
- var newValue = Interlocked.Increment(ref _filesSkipped);
- _result.FilesSkipped = newValue;
- }
+ public void IncrementFilesSkipped() => Interlocked.Increment(ref _filesSkipped);
- public void IncrementFilesConflicted() {
- var newValue = Interlocked.Increment(ref _filesConflicted);
- _result.FilesConflicted = newValue;
- }
+ public void IncrementFilesConflicted() => Interlocked.Increment(ref _filesConflicted);
+
+ public void IncrementFilesDeleted() => Interlocked.Increment(ref _filesDeleted);
- public void IncrementFilesDeleted() {
- var newValue = Interlocked.Increment(ref _filesDeleted);
- _result.FilesDeleted = newValue;
+ ///
+ /// Writes the final atomic counter values to the underlying .
+ /// Must be called after all parallel processing has completed.
+ ///
+ public void Flush() {
+ _result.FilesSynchronized = Interlocked.Read(ref _filesSynchronized);
+ _result.FilesSkipped = Interlocked.Read(ref _filesSkipped);
+ _result.FilesConflicted = Interlocked.Read(ref _filesConflicted);
+ _result.FilesDeleted = Interlocked.Read(ref _filesDeleted);
}
}