Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
4 changes: 1 addition & 3 deletions docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/SharpSync/SharpSync.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<PackageReference Include="WebDav.Client" Version="2.9.0" />
<PackageReference Include="SSH.NET" Version="2025.1.0" />
<PackageReference Include="AWSSDK.S3" Version="4.0.19.2" />
<PackageReference Include="FluentFTP" Version="53.0.2" />
<PackageReference Include="FluentFTP" Version="54.0.2" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.201" PrivateAssets="all" />
</ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/SharpSync/Sync/SyncEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

/// <summary>
Expand Down
33 changes: 17 additions & 16 deletions src/SharpSync/Sync/ThreadSafeSyncResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Oire.SharpSync.Sync;

/// <summary>
/// Thread-safe wrapper for SyncResult counters
/// Thread-safe wrapper for SyncResult counters.
/// Call <see cref="Flush"/> after all parallel processing completes
/// to write the final values to the underlying <see cref="SyncResult"/>.
/// </summary>
internal sealed class ThreadSafeSyncResult {
private readonly SyncResult _result;
Expand All @@ -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;
/// <summary>
/// Writes the final atomic counter values to the underlying <see cref="SyncResult"/>.
/// Must be called after all parallel processing has completed.
/// </summary>
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);
}
}