WebSocketManager Controller (DotNet DLL Worker)
A WorkManager worker written in C# that loads as a pre-compiled .NET DLL and controls WebSocket connections through the WebSocketManager gRPC service.
Topic: command.websocketmanagercontroller
Group: websocketmanagercontroller
MIME type: application/x-dotnet-dll
Architecture
Command Event (CloudEvent on command.websocketmanagercontroller)
↓
Dapr Pubsub → WorkManager → DotNetDllEngine → Process(CloudEvent)
↓
Parses command from CloudEvent.Data
↓
Calls WSM gRPC methods via Virtufin.Api.Client
↓
Returns response CloudEvent (topic: response.websocketmanagercontroller)
Building
cd dotnet
dotnet build Virtufin.Examples.WebSocketManagerController/Virtufin.Examples.WebSocketManagerController.csproj -c Release
dotnet publish produces just the worker's own DLL; the PackageWorker
MSBuild target packages it into a worker.nupkg alongside a nuspec
declaring the worker's PackageReferences as <dependencies> (not
vendored). NuGetDependencyInstaller (virtufin-workmanager) resolves
and downloads those declared dependencies itself at worker-load time.
Two assemblies never come from that download, regardless of what's declared:
| Assembly | Reason |
|---|---|
CloudNative.CloudEvents.dll |
Aliased to the WorkManager's own already-loaded copy, for type identity |
Virtufin.Worker.DevKit.dll |
Aliased to the WorkManager's own already-loaded copy (the IWorker base class DotNetDllEngine loads against) |
Running
Quick start (one command)
# Build and package (worker.zip created automatically by PackageWorker target)
dotnet publish dotnet/Virtufin.Examples.WebSocketManagerController/ -c Release -o /tmp/out
# Deploy and test
WORKER_B64=$(base64 -i /tmp/out/worker.zip | tr -d '\n')
curl -X POST http://localhost:25001/v1/workers \
-H "Content-Type: application/json" \
-d "{
\"code_source\": {\"content\": \"$WORKER_B64\"},
\"mime_type\": \"application/x-dotnet-dll\",
\"topic\": \"command.websocketmanagercontroller\",
\"group\": \"websocketmanagercontroller\"
}" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" | xargs -I{} curl -X POST http://localhost:25001/v1/workers/{}/start
Manual deployment
# Build and package (worker.zip created automatically)
dotnet publish dotnet/Virtufin.Examples.WebSocketManagerController/ -c Release -o /tmp/out
# Deploy worker
WORKER_B64=$(base64 -i /tmp/out/worker.zip | tr -d '\n')
curl -X POST http://localhost:25001/v1/workers \
-H "Content-Type: application/json" \
-d "{
\"code_source\": {\"content\": \"$WORKER_B64\"},
\"mime_type\": \"application/x-dotnet-dll\",
\"topic\": \"command.websocketmanagercontroller\",
\"group\": \"websocketmanagercontroller\"
}"
# Start worker (replace ID from create response)
curl -X POST http://localhost:25001/v1/workers/{id}/start
# Send command via pub/sub
curl -X POST "http://localhost:5001/v1/pubsub/command.websocketmanagercontroller" \
-H "Content-Type: application/json" \
-d "{\"data\":\"$(echo -n '{\\\"command\\\":\\\"list\\\"}' | base64)\"}"
Commands
| Command | Input | Action |
|---|---|---|
create |
{"url": "wss://stream.binance.com:9443/stream", "auto_reconnect": true, "host": "localhost:5002"} |
Create WebSocket connection |
subscribe |
{"id": "<ws-id>", "params": ["btcusdt@depth@100ms"]} |
Subscribe to Binance streams |
unsubscribe |
{"id": "<ws-id>", "params": ["btcusdt@aggTrade"]} |
Unsubscribe from streams |
publish |
{"id": "<ws-id>", "topic": "btcusdt-depth"} |
Start publishing WS messages to Dapr topic |
stop-publish |
{"id": "<ws-id>"} |
Stop publishing |
list |
{} |
List all WebSocket connections |
disconnect |
{"id": "<ws-id>"} |
Disconnect a WebSocket |
stop |
{} |
Disconnect all WebSockets |
Response
All commands return a response.websocketmanagercontroller CloudEvent: