Files
StellaOps Bot 6a299d231f
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Add unit tests for Router configuration and transport layers
- Implemented tests for RouterConfig, RoutingOptions, StaticInstanceConfig, and RouterConfigOptions to ensure default values are set correctly.
- Added tests for RouterConfigProvider to validate configurations and ensure defaults are returned when no file is specified.
- Created tests for ConfigValidationResult to check success and error scenarios.
- Developed tests for ServiceCollectionExtensions to verify service registration for RouterConfig.
- Introduced UdpTransportTests to validate serialization, connection, request-response, and error handling in UDP transport.
- Added scripts for signing authority gaps and hashing DevPortal SDK snippets.
2025-12-05 08:01:47 +02:00

6.3 KiB

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