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); } }