Skip to content

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 bundles the worker DLL and all NuGet dependencies into the output directory and creates worker.zip via the PackageWorker MSBuild target.

The PackageWorker target excludes assemblies already provided by the WorkManager runtime:

Excluded DLL Reason
CloudNative.CloudEvents.dll WorkManager runtime library
Virtufin.Worker.DevKit.dll IWorker base class, loaded by DotNetDllEngine

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:

{"command": "create", "success": true, "id": "connection-uuid", "message": "connected"}