# 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](../implplan/BLOCKED_DEPENDENCY_TREE.md) for root blockers and dependencies. ## Delivery Tracker | # | Task ID | Status | Description | Notes | |---|---------|--------|-------------|-------| | 1 | MIG-001 | TODO | Inventory all existing WebService projects | List all services | | 2 | MIG-002 | TODO | Document HTTP routes per service | Method + Path | | 3 | MIG-010 | TODO | Document Strategy A: In-place adaptation | | | 4 | MIG-011 | TODO | Add SDK to existing WebService | | | 5 | MIG-012 | TODO | Wrap controllers in [StellaEndpoint] handlers | | | 6 | MIG-013 | TODO | Register with router alongside HTTP | | | 7 | MIG-014 | TODO | Gradual traffic shift from HTTP to router | | | 8 | MIG-020 | TODO | Document Strategy B: Clean split | | | 9 | MIG-021 | TODO | Extract domain logic to shared library | | | 10 | MIG-022 | TODO | Create new Microservice project | | | 11 | MIG-023 | TODO | Map routes to handlers | | | 12 | MIG-024 | TODO | Phase out original WebService | | | 13 | MIG-030 | TODO | Document CancellationToken wiring | | | 14 | MIG-031 | TODO | Identify async operations needing token | | | 15 | MIG-032 | TODO | Update DB calls, HTTP calls, etc. | | | 16 | MIG-040 | TODO | Document streaming migration | | | 17 | MIG-041 | TODO | Convert file upload controllers | | | 18 | MIG-042 | TODO | Convert file download controllers | | | 19 | MIG-050 | TODO | Create migration checklist template | | | 20 | MIG-051 | TODO | Create automated route inventory tool | Optional | | 21 | MIG-060 | TODO | Pilot migration: choose one WebService | | | 22 | MIG-061 | TODO | Execute pilot migration | | | 23 | MIG-062 | TODO | Document lessons learned | | | 24 | MIG-070 | TODO | Merge Router.sln into StellaOps.sln | | | 25 | MIG-071 | TODO | Update CI/CD for router components | | ## 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) ```csharp [ApiController] [Route("api/invoices")] public class InvoicesController : ControllerBase { private readonly IInvoiceService _service; [HttpPost] [Authorize(Roles = "billing-admin")] public async Task Create( [FromBody] CreateInvoiceRequest request, CancellationToken ct) // <-- Often missing! { var invoice = await _service.CreateAsync(request); return Ok(new { invoice.Id }); } } ``` ### After (Microservice Handler) ```csharp [StellaEndpoint("POST", "/api/invoices")] public sealed class CreateInvoiceEndpoint : IStellaEndpoint { private readonly IInvoiceService _service; public CreateInvoiceEndpoint(IInvoiceService service) => _service = service; public async Task 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) ```csharp [HttpPost("upload")] public async Task Upload(IFormFile file) { using var stream = file.OpenReadStream(); await _storage.SaveAsync(stream); return Ok(); } ``` ### File Upload (After) ```csharp [StellaEndpoint("POST", "/upload", SupportsStreaming = true)] public sealed class UploadEndpoint : IRawStellaEndpoint { public async Task HandleAsync(RawRequestContext ctx, CancellationToken ct) { await _storage.SaveAsync(ctx.Body, ct); // Body is already a stream return RawResponse.Ok(); } } ``` ## Migration Checklist Template ```markdown # 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 2. [ ] Controller-to-handler mapping guide complete 3. [ ] CancellationToken checklist complete 4. [ ] Streaming migration guide complete 5. [ ] Migration checklist template created 6. [ ] Pilot migration executed successfully 7. [ ] Router.sln merged into StellaOps.sln 8. [ ] CI/CD updated ## Execution Log | Date (UTC) | Update | Owner | |------------|--------|-------| | | | | ## 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