mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-18 14:33:19 +00:00
fix: keep running containers until stack pull/build succeeds (#1657)
* fix: keep running containers until stack pull/build succeeds Acquire images before reconcile, capture a recovery generation for compensation, and only remove classified orphans after handoff. * fix: address recovery audit blockers for safe stack updates Retire abandoned and expired recovery artifacts, probe compensated runtimes before reporting rollback success, preserve local Docker when deleting a node, validate the exact Compose invocation before capture, and repair updateStack return-contract fixtures. * fix: resolve ESLint errors blocking CI on this branch Unused-import and unused-variable errors left over from the stack deletion refactor: MeshService in stacks.ts (its opt-out cascade moved into DeployedStackDeletionService), a redundant pruneVolumes destructure in deleteDeployedStack (the real one is re-derived from the same input object inside runDeletionBody), and an unused beforeAll import in a Docker-integration test stub. Also scopes the webhook pull-action case body in a block to satisfy no-case-declarations; purely syntactic, no behavior change. * fix: harden recovery probe, cleanup retry, and failed-pull Docker test Reject absent or unhealthy expected replicas before reporting rollback success, keep cleanup records until artifacts are actually removed, fail closed when a mesh override cannot be generated, and assert a real failed pull leaves the original container running. * fix: verify recovery probe image identity and stack-scoped override paths Reject recovered runtimes that use the wrong image or leave scale-zero services running, and confine tombstone override deletion to the intent stack directory so forged cross-stack paths cannot be swept. * test: batch notification cap fixtures in a SQLite transaction Unbatched 1200-row inserts were timing out at the default 30s under CI load even though the same assertions pass in under 2s when green.
This commit is contained in:
@@ -47,7 +47,7 @@ export interface ServiceUpdateOptions {
|
||||
}
|
||||
|
||||
export type OrchestratorResult =
|
||||
| { kind: 'stack_compose_done' }
|
||||
| { kind: 'stack_compose_done'; recoveryId: string | null }
|
||||
| {
|
||||
kind: 'service_done';
|
||||
serviceName: string;
|
||||
@@ -182,10 +182,11 @@ export class StackUpdateOrchestrator {
|
||||
ctx: UpdateOperationContext,
|
||||
options: StackComposeOptions,
|
||||
): Promise<OrchestratorResult> {
|
||||
await ComposeService.getInstance(ctx.nodeId).updateStack(
|
||||
const updateResult = await ComposeService.getInstance(ctx.nodeId).updateStack(
|
||||
ctx.stackName, options.terminalWs ?? undefined, options.atomic,
|
||||
);
|
||||
return { kind: 'stack_compose_done' };
|
||||
const recoveryId = updateResult?.recoveryId ?? null;
|
||||
return { kind: 'stack_compose_done', recoveryId };
|
||||
}
|
||||
|
||||
private async executeServiceUpdate(
|
||||
@@ -195,6 +196,16 @@ export class StackUpdateOrchestrator {
|
||||
): Promise<OrchestratorResult> {
|
||||
const { nodeId, stackName } = ctx;
|
||||
|
||||
{
|
||||
const { StackUpdateRecoveryService } = await import('./StackUpdateRecoveryService');
|
||||
if (StackUpdateRecoveryService.getInstance().isRestoredCurrentPinActive(nodeId, stackName)) {
|
||||
return serviceFailed(
|
||||
'stack_recovery_pin_active',
|
||||
'This stack is pinned to a restored recovery generation. Run a full-stack Update to continue.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const loaded = await this.loadServiceSpec(nodeId, stackName, serviceName);
|
||||
if (!loaded.ok) return loaded.result;
|
||||
const { spec, services } = loaded;
|
||||
@@ -308,6 +319,16 @@ export class StackUpdateOrchestrator {
|
||||
const { nodeId, stackName } = ctx;
|
||||
const recoveryId = options.recoveryId as string;
|
||||
|
||||
{
|
||||
const { StackUpdateRecoveryService } = await import('./StackUpdateRecoveryService');
|
||||
if (StackUpdateRecoveryService.getInstance().isRestoredCurrentPinActive(nodeId, stackName)) {
|
||||
return serviceFailed(
|
||||
'stack_recovery_pin_active',
|
||||
'This stack is pinned to a restored recovery generation. Run a full-stack Update to continue.',
|
||||
{ recoveryId },
|
||||
);
|
||||
}
|
||||
}
|
||||
const recovery = ServiceUpdateRecoveryService.getInstance().get(recoveryId);
|
||||
if (
|
||||
!recovery ||
|
||||
|
||||
Reference in New Issue
Block a user