Add integration tests for migration categories and execution
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
- Implemented MigrationCategoryTests to validate migration categorization for startup, release, seed, and data migrations. - Added tests for edge cases, including null, empty, and whitespace migration names. - Created StartupMigrationHostTests to verify the behavior of the migration host with real PostgreSQL instances using Testcontainers. - Included tests for migration execution, schema creation, and handling of pending release migrations. - Added SQL migration files for testing: creating a test table, adding a column, a release migration, and seeding data.
This commit is contained in:
267
docs/router/SPRINT_7000_0010_0001_migration.md
Normal file
267
docs/router/SPRINT_7000_0010_0001_migration.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 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<IActionResult> 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<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)
|
||||
```csharp
|
||||
[HttpPost("upload")]
|
||||
public async Task<IActionResult> 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<RawResponse> 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
|
||||
Reference in New Issue
Block a user