Skip to content

.NET SDK

The .NET package is Heddle.Sdk. It provides contract records, subject helpers, shallow schema validation, and a generic worker base.

Add the package

For a local checkout:

<ProjectReference Include="../../dotnet/src/Heddle.Sdk/Heddle.Sdk.csproj" />

Once packages are published, use the NuGet package:

dotnet add package Heddle.Sdk --prerelease

Define payload and output records

internal sealed record EchoPayload(string Text);

internal sealed record EchoOutput(string Text, int Length);

TaskMessage.Payload is a JsonObject; the worker base deserializes it into TPayload using HeddleJson.Options. Output must serialize to a JsonObject.

Implement a worker

internal sealed class EchoWorker()
    : HeddleWorker<EchoPayload, EchoOutput>(workerType: "echo", tier: "local")
{
    protected override Task<WorkerOutput<EchoOutput>> ProcessAsync(
        EchoPayload payload,
        JsonObject metadata,
        CancellationToken cancellationToken)
    {
        return Task.FromResult(new WorkerOutput<EchoOutput>(
            new EchoOutput(payload.Text.ToUpperInvariant(), payload.Text.Length)));
    }
}

Run with a transport

The core SDK defines the transport boundary:

public interface IHeddleTransport : IAsyncDisposable
{
    Task PublishAsync(
        string subject,
        ReadOnlyMemory<byte> payload,
        CancellationToken cancellationToken = default);

    IAsyncEnumerable<HeddleMessage> SubscribeAsync(
        string subject,
        string? queueGroup = null,
        CancellationToken cancellationToken = default);
}

The core package includes an in-memory implementation for local examples and tests:

await using var transport = new InMemoryHeddleTransport();
await new EchoWorker().RunAsync(transport, cancellationToken);

A broker adapter can implement the same interface without changing worker code:

await new EchoWorker().RunAsync(natsTransport, cancellationToken);

Use the shipped NATS adapter package for Heddle runtime interop:

using Heddle.Sdk.Nats;

await using var transport = new NatsHeddleTransport("nats://localhost:4222");
await transport.ConnectAsync(cancellationToken);
await new EchoWorker().RunAsync(transport, cancellationToken);

The checked-in example uses InMemoryHeddleTransport so it can run without NATS while still exercising the transport loop:

dotnet run --project examples/dotnet/EchoWorker/EchoWorker.csproj

.NET notes

  • The SDK targets net8.0.
  • JSON uses System.Text.Json.
  • Enum values are serialized as snake/lowercase strings compatible with Heddle's wire schema.
  • Override ResetAsync(...) to clear temporary resources after each task.
  • Override OnMalformedMessageAsync(...) to log malformed input without crashing the subscription loop.
  • InMemoryHeddleTransport is process-local. Use a shared broker transport for a native worker that needs to talk to a running Heddle or Workshop process.
  • Heddle.Sdk.Nats uses the official NATS.Client.Core package and stays separate from the core SDK package.