QwkSync

Troubleshooting Guide

This guide helps you diagnose and resolve common issues when using QWKSync.NET.

Common Issues

Transport Not Found

Symptoms:

Causes:

Solutions:

  1. Verify transport extension is referenced: Ensure your project references the transport extension assembly. For example, if using the HTTP transport:
    <ProjectReference Include="..\..\src\QwkSync.Http\QwkSync.Http.csproj" />
    
  2. Check TransportId matches: Verify the TransportId in your profile exactly matches the transport factory’s ID (case-insensitive):
    QwkSyncProfile profile = new QwkSyncProfile
    {
      Endpoint = new Uri("https://example.com"),
      TransportId = "http" // Must match HttpTransportFactory.TransportId
    };
    
  3. Register custom transport factory: If you created a custom transport, you must use a custom QwkSyncClient with a registry that includes your factory. The default client only includes the built-in LocalFolderTransport.

Concurrency Conflicts

Symptoms:

Causes:

Solutions:

  1. Ensure previous syncs complete: Wait for the previous sync to complete before starting a new one on the same directories.

  2. Use different directories: If you need concurrent syncs, use different local inbox/outbox directories or different profiles.

  3. Check for hanging operations: If a sync appears stuck, cancel it using the CancellationToken before starting a new one.

Timeout Errors

Symptoms:

Causes:

Solutions:

  1. Increase timeout:
    TransferPolicy policy = new TransferPolicy
    {
      Timeout = TimeSpan.FromMinutes(10) // Adjust as needed
    };
    
  2. Check network connectivity: Verify the endpoint is accessible and responsive.

  3. Investigate server-side issues: If using a remote transport, check server logs and availability.

Partial Downloads

Symptoms:

Causes:

Solutions:

  1. Ensure atomic downloads are enabled: Atomic downloads are enabled by default. Verify TransferPolicy.UseAtomicDownloads is true:
    TransferPolicy policy = new TransferPolicy
    {
      UseAtomicDownloads = true // Default, but verify
    };
    
  2. Check for cancellation: If a sync was cancelled mid-transfer, temporary files are cleaned up automatically. Retry the sync.

  3. Verify temp file handling: Atomic downloads write to temporary files first, then move into place. Ensure the local inbox directory has write permissions.

No Files Discovered

Symptoms:

Causes:

Solutions:

  1. Verify search patterns: Check that PacketDiscovery.QwkSearchPattern and PacketDiscovery.RepSearchPattern match your file naming:
    PacketDiscovery discovery = new PacketDiscovery
    {
      QwkSearchPattern = "*.qwk", // Verify this matches your files
      RepSearchPattern = "*.rep"
    };
    
  2. Check remote paths: Ensure RemoteInboxPath and RemoteOutboxPath are correct for your transport:
    PacketDiscovery discovery = new PacketDiscovery
    {
      RemoteInboxPath = "inbox", // Verify this path exists
      RemoteOutboxPath = "outbox"
    };
    
  3. Test with LocalFolderTransport: Use LocalFolderTransport to verify file discovery locally before testing with remote transports.

  4. Verify file permissions: Ensure the transport has read permissions for listing files.

Upload Failures

Symptoms:

Causes:

Solutions:

  1. Check remote path: Verify RemoteOutboxPath in PacketDiscovery is correct and writable.

  2. Verify credentials: If authentication is required, ensure QwkSyncProfile.Credentials is configured appropriately for your transport.

  3. Check file permissions: Ensure your local outbox files are readable.

  4. Test connectivity: Verify you can manually access the remote endpoint.

Exception Not Caught

Symptoms:

Causes:

Solutions:

  1. Handle concurrency exceptions:
    try
    {
      QwkSyncResult result = await client.SyncAsync(profile, plan, cancellationToken);
    }
    catch (QwkSyncConcurrencyException ex)
    {
      // Handle concurrency conflict
      Console.WriteLine($"Sync conflict: {ex.Message}");
    }
    catch (OperationCanceledException)
    {
      // Handle cancellation
      Console.WriteLine("Sync was cancelled");
    }
    
  2. Check transport implementation: If using a custom transport, verify it handles errors appropriately and does not throw unexpected exceptions.

Progress Not Reported

Symptoms:

Causes:

Solutions:

  1. Provide progress reporter:
    QwkSyncPlan plan = new QwkSyncPlan
    {
      LocalInboxDirectory = "/path/to/inbox",
      LocalOutboxDirectory = "/path/to/outbox",
      Progress = new MyProgressReporter()
    };
    
  2. Check transport support: Not all transports may support progress reporting. Verify your transport implements progress reporting for download and upload operations.

Temporary Files Not Cleaned Up

Symptoms:

Causes:

Solutions:

  1. Allow sync to complete or cancel properly: Ensure syncs are allowed to complete or are cancelled via CancellationToken. Cleanup occurs automatically on normal completion or cancellation.

  2. Manual cleanup: If temporary files remain due to abnormal termination, they can be safely deleted. They are only used during atomic download operations.

  3. Verify directory permissions: Ensure the local inbox directory allows file deletion for cleanup operations.

Debugging Tips

Enable Logging

Provide a log sink to see detailed operation information:

QwkSyncPlan plan = new QwkSyncPlan
{
  LocalInboxDirectory = "/path/to/inbox",
  LocalOutboxDirectory = "/path/to/outbox",
  Log = new ConsoleLogSink() // Implement ISyncLogSink
};

Use LocalFolderTransport for Testing

Test with LocalFolderTransport first to isolate transport-specific issues:

QwkSyncProfile profile = new QwkSyncProfile
{
  Endpoint = new Uri("file:///path/to/test/folder"),
  TransportId = "local-folder"
};

Verify Profile Configuration

Double-check all profile settings match your environment:

Console.WriteLine($"Endpoint: {profile.Endpoint}");
Console.WriteLine($"TransportId: {profile.TransportId}");
Console.WriteLine($"Credentials: {profile.Credentials}");

Check Result Details

Always inspect QwkSyncResult for detailed information:

QwkSyncResult result = await client.SyncAsync(profile, plan, cancellationToken);

Console.WriteLine($"Outcome: {result.Outcome}");
Console.WriteLine($"Issues: {result.Issues.Count}");

foreach (QwkSyncIssue issue in result.Issues)
{
  Console.WriteLine($"  - {issue.Description}");
}

Getting Further Help

If you cannot resolve an issue using this guide:

  1. Review README.md for design principles and constraints
  2. Check Public API for API details
  3. Review Concurrency Model for concurrency behaviour
  4. Review Error Model for error handling behaviour
  5. Examine transport-specific documentation if using an extension
  6. Report issues through the repository’s issue tracker with:
    • QWKSync.NET version
    • Transport type and version
    • Complete error messages
    • Minimal reproduction code