34 lines
2.6 KiB
TypeScript
34 lines
2.6 KiB
TypeScript
import { db } from '../db/index.js';
|
|
import { planScaling } from './planner.js';
|
|
import { scalingSnapshot } from './snapshot.js';
|
|
import { liveScaling, type ScalingPolicy, type ScalingDecision } from '../../autoscaling.js';
|
|
import { deploymentStage } from '../provisioning/history.js';
|
|
|
|
export interface ScalingIntent { policy_id: string; revision: number; decision: string; operation_id: string }
|
|
export function scalingIntent(operationId: string): ScalingIntent | undefined {
|
|
return db().prepare('SELECT policy_id,revision,decision,operation_id FROM autoscaling_decisions WHERE operation_id=? AND resolved=0').get(operationId) as ScalingIntent | undefined;
|
|
}
|
|
/** Rechecked before placement, after asynchronous preparation, and before dispatch. */
|
|
export function scalingAdmission(operationId: string): string | null {
|
|
const intent = scalingIntent(operationId);
|
|
if (!intent) return null;
|
|
const row = db().prepare('SELECT * FROM autoscaling_policies WHERE id=?').get(intent.policy_id) as { id: string; settings: string; mode: ScalingPolicy['mode']; revision: number; paused_reason: string | null; owns_map: number } | undefined;
|
|
let reason: string | null = null;
|
|
const paused = (db().prepare("SELECT value FROM settings WHERE key='autoscaling_paused'").get() as { value: string } | undefined)?.value === '1';
|
|
if (!row || !liveScaling(row.mode) || !row.owns_map || row.revision !== intent.revision || row.paused_reason || paused) reason = 'Autoscaling policy is paused or changed.';
|
|
else {
|
|
const policy: ScalingPolicy = { ...JSON.parse(row.settings), id: row.id, mode: row.mode, revision: row.revision, nextActionAt: 0, pausedReason: null, updatedAt: '' };
|
|
const requested = JSON.parse(intent.decision) as ScalingDecision;
|
|
if (requested.action === 'destroy' && row.mode !== 'create-destroy') return 'Automatic removal is disabled.';
|
|
const snapshot = scalingSnapshot(policy, Date.now(), operationId);
|
|
if (requested.action === 'create') {
|
|
snapshot.reservedNames = snapshot.reservedNames.filter(n => n !== requested.server);
|
|
snapshot.blockers = snapshot.blockers.filter(b => b !== `Unresolved native instance ${requested.server}.`);
|
|
}
|
|
const current = planScaling(policy, snapshot, Date.now());
|
|
if (current.action !== requested.action || current.server !== requested.server) reason = `Autoscaling intent no longer eligible: ${current.reason}`;
|
|
}
|
|
if (reason) deploymentStage(operationId, reason, { blocker: { code: 'autoscaling', message: reason, automatic: true } });
|
|
return reason;
|
|
}
|