Files
StellaOps Bot f1a39c4ce3
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
up
2025-12-13 18:08:55 +02:00
..
up
2025-12-13 18:08:55 +02:00

StellaOps Router Example

This example demonstrates the StellaOps Router, Gateway, and Microservice SDK working together.

Overview

The example includes:

  • Examples.Gateway - HTTP gateway that routes requests to microservices
  • Examples.Billing.Microservice - Sample billing service with typed and streaming endpoints
  • Examples.Inventory.Microservice - Sample inventory service demonstrating multi-service routing
  • Examples.Integration.Tests - End-to-end integration tests

Prerequisites

  • .NET 10 SDK
  • Docker and Docker Compose (for containerized deployment)

Project Structure

examples/router/
├── Examples.Router.sln
├── docker-compose.yaml
├── README.md
├── src/
│   ├── Examples.Gateway/
│   │   ├── Program.cs
│   │   ├── router.yaml
│   │   └── appsettings.json
│   ├── Examples.Billing.Microservice/
│   │   ├── Program.cs
│   │   ├── microservice.yaml
│   │   └── Endpoints/
│   │       ├── CreateInvoiceEndpoint.cs
│   │       ├── GetInvoiceEndpoint.cs
│   │       └── UploadAttachmentEndpoint.cs
│   └── Examples.Inventory.Microservice/
│       ├── Program.cs
│       └── Endpoints/
│           ├── ListItemsEndpoint.cs
│           └── GetItemEndpoint.cs
└── tests/
    └── Examples.Integration.Tests/

Running Locally

Build the Solution

cd examples/router
dotnet build Examples.Router.sln

Run with Docker Compose

docker-compose up --build

This starts:

  • Gateway on port 8080 (HTTP) and 5100 (TCP transport)
  • Billing microservice
  • Inventory microservice
  • RabbitMQ (optional, for message-based transport)

Run Without Docker

Start each service in separate terminals:

# Terminal 1: Gateway
cd src/Examples.Gateway
dotnet run

# Terminal 2: Billing Microservice
cd src/Examples.Billing.Microservice
dotnet run

# Terminal 3: Inventory Microservice
cd src/Examples.Inventory.Microservice
dotnet run

Example API Calls

Billing Service

Create an invoice:

curl -X POST http://localhost:8080/invoices \
  -H "Content-Type: application/json" \
  -d '{"customerId": "CUST-001", "amount": 99.99, "description": "Service fee"}'

Get an invoice:

curl http://localhost:8080/invoices/INV-12345

Upload an attachment (streaming):

curl -X POST http://localhost:8080/invoices/INV-12345/attachments \
  -H "Content-Type: application/octet-stream" \
  --data-binary @document.pdf

Inventory Service

List items:

curl "http://localhost:8080/items?page=1&pageSize=20"

List items by category:

curl "http://localhost:8080/items?category=widgets"

Get a specific item:

curl http://localhost:8080/items/SKU-001

Adding New Endpoints

1. Create the Endpoint Class

using StellaOps.Microservice;

[StellaEndpoint("POST", "/orders", TimeoutSeconds = 30)]
public sealed class CreateOrderEndpoint : IStellaEndpoint<CreateOrderRequest, CreateOrderResponse>
{
    public Task<CreateOrderResponse> HandleAsync(
        CreateOrderRequest request,
        CancellationToken cancellationToken)
    {
        // Implementation
        return Task.FromResult(new CreateOrderResponse { OrderId = "ORD-123" });
    }
}

2. Register in Program.cs

builder.Services.AddScoped<CreateOrderEndpoint>();

3. Update router.yaml (if needed)

Add routing rules for the new endpoint path.

Streaming Endpoints

For endpoints that handle large payloads (file uploads, etc.), implement IRawStellaEndpoint:

[StellaEndpoint("POST", "/files/{id}", SupportsStreaming = true)]
public sealed class UploadFileEndpoint : IRawStellaEndpoint
{
    public async Task<RawResponse> HandleAsync(
        RawRequestContext context,
        CancellationToken cancellationToken)
    {
        var id = context.PathParameters["id"];

        // Stream body directly without buffering
        await using var stream = context.Body;
        // Process stream...

        return RawResponse.Ok("{}");
    }
}

Cancellation Behavior

All endpoints receive a CancellationToken that is triggered when:

  1. The client disconnects
  2. The request timeout is exceeded
  3. The gateway shuts down

Always respect the cancellation token in long-running operations:

public async Task<Response> HandleAsync(Request request, CancellationToken ct)
{
    // Check cancellation periodically
    ct.ThrowIfCancellationRequested();

    // Or pass to async operations
    await SomeLongOperation(ct);
}

Payload Limits

Default limits are configured in router.yaml:

payloadLimits:
  maxRequestBodySizeBytes: 10485760  # 10 MB
  maxChunkSizeBytes: 65536           # 64 KB

For streaming endpoints, the body is not buffered so these limits apply per-chunk.

Running Tests

cd tests/Examples.Integration.Tests
dotnet test

The integration tests verify:

  • End-to-end request routing
  • Multi-service registration
  • Streaming uploads
  • Request cancellation
  • Payload limit enforcement

Configuration

Gateway (router.yaml)

# Microservice routing rules
services:
  billing:
    routes:
      - path: /invoices
        methods: [GET, POST]
      - path: /invoices/{id}
        methods: [GET, PUT, DELETE]
      - path: /invoices/{id}/attachments
        methods: [POST]
  inventory:
    routes:
      - path: /items
        methods: [GET]
      - path: /items/{sku}
        methods: [GET]

Microservice (microservice.yaml)

service:
  name: billing
  version: 1.0.0
  region: demo

endpoints:
  - path: /invoices
    method: POST
    timeoutSeconds: 30
  - path: /invoices/{id}
    method: GET
    timeoutSeconds: 10

routers:
  - host: localhost
    port: 5100
    transportType: InMemory

Troubleshooting

Microservice not registering

Check that:

  1. Gateway is running and healthy
  2. Router host/port in microservice.yaml matches gateway
  3. Network connectivity between services

Request timeouts

Increase the timeout in the endpoint attribute:

[StellaEndpoint("POST", "/long-operation", TimeoutSeconds = 120)]

Streaming not working

Ensure the endpoint:

  1. Is marked with SupportsStreaming = true
  2. Implements IRawStellaEndpoint
  3. Does not buffer the entire body before processing

License

AGPL-3.0-or-later