Queue native collection launches before async placement

This commit is contained in:
2026-10-05 11:35:50 -04:00
parent 1405114a14
commit 7c76851252
34 changed files with 1324 additions and 244 deletions
+15 -8
View File
@@ -6,9 +6,13 @@ import { recordProgress } from './progress.js';
export function canCancelCreation(id: string): boolean {
return !!db().prepare(`SELECT 1 FROM server_deployments d
JOIN native_provisioning n ON n.deployment_id=d.id
JOIN native_instances i ON i.id=n.instance_id AND i.generation=n.generation AND i.retired_at IS NULL
LEFT JOIN native_provisioning n ON n.deployment_id=d.id
LEFT JOIN native_instances i ON i.id=n.instance_id AND i.generation=n.generation AND i.retired_at IS NULL
WHERE d.id=? AND d.action='create' AND d.server_deleted_at IS NULL
AND (i.id IS NOT NULL OR (n.deployment_id IS NULL
AND EXISTS (SELECT 1 FROM native_creation_intents intent WHERE intent.deployment_id=d.id)
AND NOT EXISTS (SELECT 1 FROM native_instances replacement WHERE replacement.server=d.server AND replacement.retired_at IS NULL)
AND NOT EXISTS (SELECT 1 FROM servers replacement WHERE replacement.name=d.server AND replacement.destroyed_at IS NULL)))
AND d.state IN ('queued','waiting','running','awaiting-health','interrupted','failed')
AND NOT EXISTS (SELECT 1 FROM server_deployments other WHERE other.server=d.server
AND other.server_deleted_at IS NULL AND other.rowid>d.rowid AND other.state!='cancelled'
@@ -23,9 +27,9 @@ export function cancelCreation(id: string, triggeredBy = 'ui'): string | null {
if (prior) return prior.cleanup_id;
if (!canCancelCreation(id)) return null;
const job = db().prepare(`SELECT d.server,n.operation_id,n.stage_operation_id FROM server_deployments d
JOIN native_provisioning n ON n.deployment_id=d.id WHERE d.id=?`).get(id) as
LEFT JOIN native_provisioning n ON n.deployment_id=d.id WHERE d.id=?`).get(id) as
{ server: string; operation_id: string | null; stage_operation_id: string | null };
const instance = nativeInstance(job.server)!;
const instance = nativeInstance(job.server);
// Replace a removal still waiting on occupancy, including one whose asynchronous probe is outstanding.
for (const removal of db().prepare("SELECT id FROM server_deployments WHERE server=? AND action='destroy' AND state='waiting' AND server_deleted_at IS NULL").all(job.server) as { id: string }[]) {
cancelRemoval(removal.id);
@@ -37,13 +41,16 @@ export function cancelCreation(id: string, triggeredBy = 'ui'): string | null {
event: { kind: 'cancelled', message: 'Creation cancelled. Its partial instance will be removed without a player-count check.', details: { cleanupId } } });
if (!job.operation_id && !job.stage_operation_id) {
// No remote mutation was ever queued. The reservation is the only resource to remove.
db().prepare('UPDATE native_instances SET retired_at=? WHERE id=?').run(new Date().toISOString(), instance.id);
releaseHostPorts(instance.id);
if (instance) {
db().prepare('UPDATE native_instances SET retired_at=? WHERE id=?').run(new Date().toISOString(), instance.id);
releaseHostPorts(instance.id);
}
deploymentStage(cleanupId, 'Unsubmitted creation cancelled; reservations released', { phase: 'cleanup',
checkpoint: { key: 'cleanup', label: 'No host command submitted; local reservations released' } });
finishDeployment(cleanupId, { ok: true });
finishCreationCancellation(cleanupId);
} else {
if (!instance) throw new Error('The original native instance is unavailable.');
const operation = queueHostOperation(instance.host_id, 'instance.cancel-create', { createOperationId: job.operation_id ?? id },
{ instanceId: instance.id, generation: instance.generation, idempotencyKey: cleanupId });
db().prepare('UPDATE native_provisioning SET operation_id=? WHERE deployment_id=?').run(operation.id, cleanupId);
@@ -57,12 +64,12 @@ export function cancelCreation(id: string, triggeredBy = 'ui'): string | null {
export function finishCreationCancellation(cleanupId: string): void {
const cancellation = db().prepare(`SELECT c.creation_id,n.operation_id FROM native_creation_cancellations c
JOIN native_provisioning n ON n.deployment_id=c.creation_id WHERE c.cleanup_id=?`).get(cleanupId) as
LEFT JOIN native_provisioning n ON n.deployment_id=c.creation_id WHERE c.cleanup_id=?`).get(cleanupId) as
{ creation_id: string; operation_id: string | null } | undefined;
if (!cancellation) return;
const now = new Date().toISOString();
db().prepare('UPDATE server_deployments SET server_deleted_at=? WHERE id IN (?,?)').run(now, cancellation.creation_id, cleanupId);
deploymentStage(cancellation.creation_id, 'Creation cancelled; partial instance removed', { blocker: null,
deploymentStage(cancellation.creation_id, 'Creation cancelled; cleanup completed', { blocker: null,
checkpoint: { key: 'cleanup', phase: 'cleanup', label: 'Cancellation cleanup confirmed; instance and reservations removed' } });
// The original command may have lost its receipt. Cleanup proves that its effects are now gone.
if (cancellation.operation_id) {