Getting Started
This walkthrough takes the canonical WebSocketManagerController worker from a clean checkout to a running binance subscriber against a local WorkManager + Dapr stack.
Prerequisites
- .NET 10 SDK
- Python 3.11+ with
uv(for the binance.py example) - Docker (with the
docker.haenerconsulting.com/library/dotnet-crossbuild:10.0image available locally for AOT builds) - A running WorkManager + API + Dapr stack (the
docker-composerepo provides the canonicalprod.yaml)
1. Build the worker (managed)
git clone https://git.haenerconsulting.com/virtufin/virtufin-workers.git
cd virtufin-workers/WebSocketManagerController
python3 scripts/build_managed.py
This runs dotnet publish on the managed csproj, then PackageWorker (an MSBuild target in the csproj) stages the output into <repo>/build/Virtufin.Worker.WebSocketManagerController.Managed.nupkg/, computes SHA-256, and writes build_version.txt. Output:
==> PackageId: Virtufin.Worker.WebSocketManagerController
==> LIBRARY_VERSION: 0.0.8 (cli=None env=None file=0.0.8)
==> Publishing .../Virtufin.Worker.WebSocketManagerController.Managed.csproj ...
==> Built artefact: .../build/.../Virtufin.Worker.WebSocketManagerController.nupkg (714,499 bytes)
==> SHA-256: ...
==> Version: 0.0.8-sha.<8hex>
2. Publish the nupkg
python3 scripts/publish.py
Uploads the nupkg to the Gitea NuGet feed (https://gitea.haenerconsulting.com/api/packages/virtufin/nuget/). Reads the Gitea credentials from the VIRTUFIN_PACKAGES_USER / VIRTUFIN_PACKAGES_TOKEN env vars.
3. Run the binance example
cd examples
uv venv
uv pip install -r requirements.txt # if applicable
./.venv/bin/python binance.py
The script reads BUILD_DIR/build_version.txt to discover the version, downloads the nupkg, registers two workers, and issues commands to each. Output:
=== WebSocketManagerController example (abcd1234) @ ...
pairs: 50, workers: 2, conns/worker: 5
total connections: 10
publish topic: act.exchange.binance.orderbook.update
response topic: response.websocketmanagercontroller
--- Worker 1/2 ---
worker_id: ...
--- Worker 2/2 ---
worker_id: ...
→ conn 0: create... conn 0: create -> {'command': 'create', 'success': True, 'id': '...', 'message': 'connected'}
→ conn 0: subscribe...
...
=== Setup complete. Listening on act.exchange.binance.orderbook.update. ===
4. (Optional) Build the AOT variant
The same worker source can be built for NativeAOT. The AOT csproj sets <PublishAot>true</PublishAot> and produces a libWebSocketManagerControllerNative.so per RID. Build with:
python3 scripts/build_aot.py
This requires Docker to run the cross-build image (clang + cross-binutils). On an x86_64 host it works natively; on an arm64 host it works via qemu-x86_64 emulation and is slow.
To verify the AOT nupkg is well-formed (right .so exported, .supported-rids sidecar present, no managed-deps leaked):
python3 scripts/smoke_test_aot.py
5. (Optional) Build a single nupkg containing both layouts
bash scripts/build_both.sh
Produces a single nupkg with lib/net10.0/WebSocketManagerController.dll AND runtimes/<rid>/native/libWebSocketManagerController.so. Register under either or both MIME types at deploy time.
Next steps
- Worker Author Guide — author a new worker from scratch
- Packaging Modes — the trade-offs between managed, native, and both
- Engines — the DotNetDll vs NativeDll contrast in detail