Files
git.stella-ops.org/examples/router/README.md
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

298 lines
6.3 KiB
Markdown

# 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
```bash
cd examples/router
dotnet build Examples.Router.sln
```
### Run with Docker Compose
```bash
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:
```bash
# 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:
```bash
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:
```bash
curl http://localhost:8080/invoices/INV-12345
```
Upload an attachment (streaming):
```bash
curl -X POST http://localhost:8080/invoices/INV-12345/attachments \
-H "Content-Type: application/octet-stream" \
--data-binary @document.pdf
```
### Inventory Service
List items:
```bash
curl "http://localhost:8080/items?page=1&pageSize=20"
```
List items by category:
```bash
curl "http://localhost:8080/items?category=widgets"
```
Get a specific item:
```bash
curl http://localhost:8080/items/SKU-001
```
## Adding New Endpoints
### 1. Create the Endpoint Class
```csharp
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
```csharp
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`:
```csharp
[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:
```csharp
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`:
```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
```bash
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)
```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)
```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:
```csharp
[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