Files
git.stella-ops.org/docs/router/SPRINT_7000_0010_0001_migration.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

11 KiB

Sprint 7000-0010-0001 · Migration · WebService to Microservice

Topic & Scope

Define and document the migration path from existing StellaOps.*.WebService projects to the new microservice pattern with router. This is the final sprint that connects the router infrastructure to the rest of StellaOps.

Goal: Clear migration guide and tooling for converting WebServices to Microservices.

Working directories:

  • docs/router/ (migration documentation)
  • Potentially existing WebService projects (for pilot migration)

Dependencies & Concurrency

  • Upstream: All router sprints complete (7000-0001 through 7000-0009)
  • Downstream: None. Final sprint.
  • Parallel work: None.
  • Cross-module impact: YES - This sprint affects existing StellaOps modules.

Documentation Prerequisites

  • docs/router/specs.md (section 14 - Migration requirements)
  • docs/router/implplan.md (phase 11-12 guidance)
  • Existing WebService project structures

BLOCKED Tasks: Before working on BLOCKED tasks, review ../implplan/BLOCKED_DEPENDENCY_TREE.md for root blockers and dependencies.

Delivery Tracker

# Task ID Status Description Notes
1 MIG-001 DONE Inventory all existing WebService projects 19 services documented in migration-guide.md
2 MIG-002 DONE Document HTTP routes per service In migration-guide.md with examples
3 MIG-010 DONE Document Strategy A: In-place adaptation migration-guide.md section
4 MIG-011 DONE Add SDK to existing WebService Example code in migration-guide.md
5 MIG-012 DONE Wrap controllers in [StellaEndpoint] handlers Code examples provided
6 MIG-013 DONE Register with router alongside HTTP Documented in guide
7 MIG-014 DONE Gradual traffic shift from HTTP to router Cutover section in guide
8 MIG-020 DONE Document Strategy B: Clean split migration-guide.md section
9 MIG-021 DONE Extract domain logic to shared library Step-by-step in guide
10 MIG-022 DONE Create new Microservice project Template in examples/router
11 MIG-023 DONE Map routes to handlers Controller-to-handler mapping section
12 MIG-024 DONE Phase out original WebService Cleanup section in guide
13 MIG-030 DONE Document CancellationToken wiring Comprehensive checklist in guide
14 MIG-031 DONE Identify async operations needing token Checklist with examples
15 MIG-032 DONE Update DB calls, HTTP calls, etc. Before/after examples
16 MIG-040 DONE Document streaming migration IRawStellaEndpoint examples
17 MIG-041 DONE Convert file upload controllers Before/after examples
18 MIG-042 DONE Convert file download controllers Before/after examples
19 MIG-050 DONE Create migration checklist template In migration-guide.md
20 MIG-051 SKIP Create automated route inventory tool Optional - not needed
21 MIG-060 SKIP Pilot migration: choose one WebService Deferred to team
22 MIG-061 SKIP Execute pilot migration Deferred to team
23 MIG-062 SKIP Document lessons learned Deferred to team
24 MIG-070 DONE Merge Router.sln into StellaOps.sln All projects added
25 MIG-071 DONE Update CI/CD for router components Added to build-test-deploy.yml

Migration Strategies

Strategy A: In-Place Adaptation

Best for: Services that need to maintain HTTP compatibility during transition.

┌─────────────────────────────────────┐
│  StellaOps.Billing.WebService       │
│  ┌─────────────────────────────┐    │
│  │  Existing HTTP Controllers  │◄───┼──── HTTP clients (legacy)
│  └─────────────────────────────┘    │
│  ┌─────────────────────────────┐    │
│  │  [StellaEndpoint] Handlers  │◄───┼──── Router (new)
│  └─────────────────────────────┘    │
│  ┌─────────────────────────────┐    │
│  │  Shared Domain Logic        │    │
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘

Steps:

  1. Add StellaOps.Microservice package reference
  2. Create handler classes for each route
  3. Handlers call existing service layer
  4. Register with router pool
  5. Test via router
  6. Shift traffic gradually
  7. Remove HTTP controllers when ready

Strategy B: Clean Split

Best for: Major refactoring or when HTTP compatibility not needed.

┌─────────────────────────────────────┐
│  StellaOps.Billing.Domain           │  ◄── Shared library
│  (extracted business logic)         │
└─────────────────────────────────────┘
          ▲                 ▲
          │                 │
┌─────────┴───────┐ ┌───────┴─────────┐
│ (Legacy)        │ │ (New)           │
│ Billing.Web     │ │ Billing.Micro   │
│ Service         │ │ service         │
│ HTTP only       │ │ Router only     │
└─────────────────┘ └─────────────────┘

Steps:

  1. Extract domain logic to .Domain library
  2. Create new .Microservice project
  3. Implement handlers using domain library
  4. Deploy alongside WebService
  5. Shift traffic to router
  6. Deprecate WebService

Controller to Handler Mapping

Before (ASP.NET Controller)

[ApiController]
[Route("api/invoices")]
public class InvoicesController : ControllerBase
{
    private readonly IInvoiceService _service;

    [HttpPost]
    [Authorize(Roles = "billing-admin")]
    public async Task<IActionResult> Create(
        [FromBody] CreateInvoiceRequest request,
        CancellationToken ct)  // <-- Often missing!
    {
        var invoice = await _service.CreateAsync(request);
        return Ok(new { invoice.Id });
    }
}

After (Microservice Handler)

[StellaEndpoint("POST", "/api/invoices")]
public sealed class CreateInvoiceEndpoint : IStellaEndpoint<CreateInvoiceRequest, CreateInvoiceResponse>
{
    private readonly IInvoiceService _service;

    public CreateInvoiceEndpoint(IInvoiceService service) => _service = service;

    public async Task<CreateInvoiceResponse> HandleAsync(
        CreateInvoiceRequest request,
        CancellationToken ct)  // <-- Required, propagated
    {
        var invoice = await _service.CreateAsync(request, ct);  // Pass token!
        return new CreateInvoiceResponse { InvoiceId = invoice.Id };
    }
}

CancellationToken Checklist

For each migrated handler, verify:

  • Handler accepts CancellationToken parameter
  • Token passed to all database calls
  • Token passed to all HTTP client calls
  • Token passed to all file I/O operations
  • Long-running loops check ct.IsCancellationRequested
  • Token passed to Task.Delay, WaitAsync, etc.

Streaming Migration

File Upload (Before)

[HttpPost("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
    using var stream = file.OpenReadStream();
    await _storage.SaveAsync(stream);
    return Ok();
}

File Upload (After)

[StellaEndpoint("POST", "/upload", SupportsStreaming = true)]
public sealed class UploadEndpoint : IRawStellaEndpoint
{
    public async Task<RawResponse> HandleAsync(RawRequestContext ctx, CancellationToken ct)
    {
        await _storage.SaveAsync(ctx.Body, ct);  // Body is already a stream
        return RawResponse.Ok();
    }
}

Migration Checklist Template

# Migration Checklist: [ServiceName]

## Inventory
- [ ] List all HTTP routes (Method + Path)
- [ ] Identify streaming endpoints
- [ ] Identify authorization requirements
- [ ] Document external dependencies

## Preparation
- [ ] Add StellaOps.Microservice package
- [ ] Configure router connection
- [ ] Set up local gateway for testing

## Per-Route Migration
For each route:
- [ ] Create [StellaEndpoint] handler class
- [ ] Map request/response types
- [ ] Wire CancellationToken throughout
- [ ] Convert to IRawStellaEndpoint if streaming
- [ ] Write unit tests
- [ ] Write integration tests

## Cutover
- [ ] Deploy alongside existing WebService
- [ ] Verify via router routing
- [ ] Shift percentage of traffic
- [ ] Monitor for errors
- [ ] Full cutover
- [ ] Remove WebService HTTP listeners

## Cleanup
- [ ] Remove unused controller code
- [ ] Remove HTTP pipeline configuration
- [ ] Update documentation

StellaOps Modules to Migrate

Module WebService Priority Complexity
Concelier StellaOps.Concelier.WebService High Medium
Scanner StellaOps.Scanner.WebService High High (streaming)
Authority StellaOps.Authority.WebService Medium Low
Orchestrator StellaOps.Orchestrator.WebService Medium Medium
Scheduler StellaOps.Scheduler.WebService Low Low
Notify StellaOps.Notify.WebService Low Low

Exit Criteria

Before marking this sprint DONE:

  1. Migration strategies documented (migration-guide.md)
  2. Controller-to-handler mapping guide complete (migration-guide.md)
  3. CancellationToken checklist complete (migration-guide.md)
  4. Streaming migration guide complete (migration-guide.md)
  5. Migration checklist template created (migration-guide.md)
  6. [~] Pilot migration executed successfully (deferred to team for actual service migration)
  7. Router.sln merged into StellaOps.sln
  8. CI/CD updated (build-test-deploy.yml)

Execution Log

Date (UTC) Update Owner
2024-12-04 Created comprehensive migration-guide.md with strategies, examples, and service inventory Claude
2024-12-04 Added all Router projects to StellaOps.sln (Microservice SDK, Config, Transports) Claude
2024-12-04 Updated build-test-deploy.yml with Router component build and test steps Claude

Decisions & Risks

  • Pilot migration should be a low-risk service first
  • Strategy A preferred for gradual transition
  • Strategy B preferred for greenfield-like rewrites
  • CancellationToken wiring is the #1 source of migration bugs
  • Streaming endpoints require IRawStellaEndpoint, not typed handlers
  • Authorization migrates from [Authorize(Roles)] to RequiringClaims