QwkSync

Frequently Asked Questions

General Questions

What is QWKSync.NET?

QWKSync.NET is a small, dependency-free .NET library that safely and predictably moves QWK and REP files between a local application and a remote endpoint. It operates strictly at the transport and orchestration level and does not parse, validate, or interpret packet contents.

What does QWKSync.NET do?

QWKSync.NET:

It does not understand what those files mean. All packet semantics belong to your application.

What does QWKSync.NET not do?

QWKSync.NET is not:

If a feature requires knowing what is inside a packet, it does not belong in QWKSync.NET.

Why is QWKSync.NET so narrow in scope?

The narrow scope is intentional and provides value. By focusing only on file transport and orchestration, QWKSync.NET remains:

Transports

What transports are available?

QWKSync.NET ships with exactly one built-in transport:

All network protocols (HTTP, FTP, SFTP, etc.) are provided as external extension assemblies.

How do I use a different transport?

Create a profile with the appropriate TransportId:

QwkSyncProfile profile = new QwkSyncProfile
{
  Endpoint = new Uri("https://example.com/api"),
  TransportId = "http"
};

You must ensure the transport extension assembly is referenced in your project and that the transport factory is registered.

Can I create my own transport?

Yes. See Creating Transport Extensions for detailed instructions.

Does QWKSync.NET define an HTTP wire protocol?

No. QWKSync.NET does not define any HTTP wire protocol. If you need HTTP transport functionality, you must implement a transport extension that defines and implements your chosen protocol contract.

Configuration

What are the defaults?

QWKSync.NET defaults are intentionally conservative:

Any deviation from these defaults must be explicitly configured.

How do I enable retries?

Configure TransferPolicy with MaxRetries:

TransferPolicy policy = new TransferPolicy
{
  MaxRetries = 3
};

QwkSyncPlan plan = new QwkSyncPlan
{
  LocalInboxDirectory = "/path/to/inbox",
  LocalOutboxDirectory = "/path/to/outbox",
  Transfer = policy
};

How do I change the timeout?

Configure TransferPolicy with Timeout:

TransferPolicy policy = new TransferPolicy
{
  Timeout = TimeSpan.FromMinutes(5)
};

The timeout applies per individual transfer operation (each list, download, upload, move, or delete call).

How do I customise file discovery?

Configure PacketDiscovery:

PacketDiscovery discovery = new PacketDiscovery
{
  QwkSearchPattern = "*.qwk",
  RepSearchPattern = "*.rep",
  PickStrategy = PacketPickStrategy.Newest,
  RemoteInboxPath = "inbox",
  RemoteOutboxPath = "outbox"
};

QwkSyncPlan plan = new QwkSyncPlan
{
  LocalInboxDirectory = "/path/to/inbox",
  LocalOutboxDirectory = "/path/to/outbox",
  Discovery = discovery
};

Packet Handling

How many packets can I sync?

QWKSync.NET makes no assumptions about packet counts or relationships. A sync session may:

There is no assumed pairing between QWK and REP files.

Does QWKSync.NET validate packet contents?

No. QWKSync.NET treats .qwk and .rep files as opaque binary files. It does not validate, parse, or interpret packet semantics. Validation and parsing belong in your application code or a separate QWK parsing library, such as QWK.NET.

How are packets ordered?

Packets are ordered deterministically using the PickStrategy specified in PacketDiscovery. The default strategy is PacketPickStrategy.Newest.

Error Handling

What happens when a sync fails?

QWKSync.NET returns a QwkSyncResult with:

Individual transfer failures are captured as issues. The operation continues to attempt remaining transfers unless cancelled.

What exceptions might be thrown?

QWKSync.NET may throw:

How do I handle partial failures?

Check the Outcome and Issues properties of QwkSyncResult:

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

if (result.Outcome == QwkSyncOutcome.PartialSuccess)
{
  foreach (QwkSyncIssue issue in result.Issues)
  {
    Console.WriteLine($"Issue: {issue.Description}");
  }
}

Concurrency

Can I run multiple syncs concurrently?

QWKSync.NET enforces a single-flight guarantee: only one sync can operate on the same local inbox directory, local outbox directory, or profile scope at a time. Attempting concurrent syncs will throw QwkSyncConcurrencyException.

How do I cancel a sync operation?

Pass a CancellationToken to SyncAsync and cancel the token source:

using CancellationTokenSource cts = new CancellationTokenSource();

// Later, to cancel:
cts.Cancel();

await client.SyncAsync(profile, plan, cts.Token);

Cancellation interrupts I/O promptly and triggers cleanup of temporary files.

Licensing and Dependencies

What dependencies does QWKSync.NET have?

QWKSync.NET has zero third-party dependencies. It relies only on the .NET Base Class Library (BCL).

Is QWKSync.NET free to use?

Yes, QWKSync.NET is MIT licensed.

Getting Help

Where can I find more information?

How do I report a bug?

Please report bugs through the repository’s issue tracker.