- 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.
11 KiB
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:
- Add
StellaOps.Microservicepackage reference - Create handler classes for each route
- Handlers call existing service layer
- Register with router pool
- Test via router
- Shift traffic gradually
- 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:
- Extract domain logic to
.Domainlibrary - Create new
.Microserviceproject - Implement handlers using domain library
- Deploy alongside WebService
- Shift traffic to router
- 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:
- Migration strategies documented (migration-guide.md)
- Controller-to-handler mapping guide complete (migration-guide.md)
- CancellationToken checklist complete (migration-guide.md)
- Streaming migration guide complete (migration-guide.md)
- Migration checklist template created (migration-guide.md)
- [~] Pilot migration executed successfully (deferred to team for actual service migration)
- Router.sln merged into StellaOps.sln
- 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