Add safe manual instance rebalancing

This commit is contained in:
2026-10-08 12:37:56 -04:00
parent 26de43639f
commit 012cd51a66
45 changed files with 2006 additions and 154 deletions
+26
View File
@@ -0,0 +1,26 @@
import { db } from '../db/index.js';
import type { RebalanceCandidate, RebalanceSettings } from '../../rebalancing.js';
import { rebalanceMoveBlocker } from './planner.js';
import { rebalanceSnapshot } from './snapshot.js';
/** A delivered migration must finish even after the operator stops its parent run. */
export function rebalanceAdmission(operationId: string): string | null {
const operation = db().prepare('SELECT triggered_by FROM server_deployments WHERE id=?').get(operationId) as { triggered_by: string } | undefined;
if (!operation?.triggered_by.startsWith('rebalance:')) return null;
const migration = db().prepare('SELECT remove_operation_id,removed_at FROM ec_host_migrations WHERE deployment_id=?')
.get(operationId) as { remove_operation_id: string | null; removed_at: string | null } | undefined;
if (migration?.remove_operation_id || migration?.removed_at) return null;
const row = db().prepare(`SELECT m.candidate,r.settings,r.state FROM rebalancing_moves m
JOIN rebalancing_runs r ON r.id=m.run_id WHERE m.operation_id=? AND m.state='moving'`).get(operationId) as
{ candidate: string; settings: string; state: string } | undefined;
if (!row || row.state !== 'running') return 'Rebalance run is no longer requesting this move.';
const settings = JSON.parse(row.settings) as RebalanceSettings;
return rebalanceMoveBlocker(rebalanceSnapshot(settings, operationId), JSON.parse(row.candidate) as RebalanceCandidate);
}
/** Cancelling an individual uncommitted move also withdraws the rest of that run. */
export function requestRebalanceStopForOperation(operationId: string): void {
db().prepare(`UPDATE rebalancing_runs SET state='stopping',updated_at=?,message='Stopping after the current move.'
WHERE state='running' AND id IN (SELECT run_id FROM rebalancing_moves WHERE operation_id=?)`)
.run(new Date().toISOString(), operationId);
}