Require full key coverage when saving autoscaling policies
This commit is contained in:
@@ -30,12 +30,16 @@ export function previewScaling(input: unknown, id?: string, revision?: number):
|
||||
nextActionAt: existing?.nextActionAt ?? 0, pausedReason: null, updatedAt: existing?.updatedAt ?? '' };
|
||||
const snapshot = scalingSnapshot(policy);
|
||||
const blockers: string[] = [];
|
||||
// Creating any policy requires full coverage; existing policies must always be pausable.
|
||||
if (!existing || policy.mode !== 'off') {
|
||||
for (const map of zombieMaps(policy.game).filter(m => policy.mapSlug === '*' || m.slug === policy.mapSlug)) {
|
||||
const count = snapshot.keyedNames.filter(name => parseServerName(name)?.mapSlug === map.slug).length;
|
||||
if (count < policy.maximum) blockers.push(`Save keys for at least ${policy.maximum} lobby identities for ${map.friendly} before saving this policy (${count} saved; ${policy.maximum - count} more required).`);
|
||||
}
|
||||
}
|
||||
if (liveScaling(policy.mode)) {
|
||||
const owner = scalingOwner(policy.game, policy.mapSlug);
|
||||
if (owner && owner !== policy.id) blockers.push(`An overlapping policy owns this lineup. Pause it and settle pending work first: /autoscaling#${owner}`);
|
||||
for (const map of zombieMaps(policy.game).filter(m => policy.mapSlug === '*' || m.slug === policy.mapSlug)) {
|
||||
if (snapshot.keyedNames.filter(name => parseServerName(name)?.mapSlug === map.slug).length < policy.maximum) blockers.push(`Save keys for at least ${policy.maximum} lobby identities for ${map.friendly} before activating this policy.`);
|
||||
}
|
||||
blockers.push(...snapshot.blockers);
|
||||
for (const member of snapshot.members) if (!['occupied', 'empty'].includes(member.state)) blockers.push(`${member.name}: ${member.blocker ?? member.state}. Settle this work before activation.`);
|
||||
if (policy.mode === 'create-destroy') for (const member of snapshot.members) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { db } from '../db/index.js';
|
||||
import { validServerId } from '../fleet/server-keys.js';
|
||||
import { listServers, type ServerRow } from '../fleet/servers.js';
|
||||
import { observationReader } from '../fleet/status.js';
|
||||
import { parseServerName, zombieMaps } from '../../map-aliases.js';
|
||||
@@ -72,6 +73,6 @@ export function scalingSnapshot(policy: ScalingPolicy, now = Date.now(), exceptO
|
||||
reservedNames.add(row.name);
|
||||
if (!members.some(m => m.name === row.name)) blockers.push(`Unresolved native instance ${row.name}.`);
|
||||
}
|
||||
const keyedNames = (handle.prepare("SELECT server_id AS name FROM server_keys WHERE length(trim(pluto_key))>0").all() as { name: string }[]).filter(matches).map(r => r.name);
|
||||
const keyedNames = (handle.prepare("SELECT server_id AS name FROM server_keys WHERE length(trim(pluto_key))>0").all() as { name: string }[]).filter(row => validServerId(row.name) && matches(row)).map(r => r.name);
|
||||
return { members, reservedNames: [...reservedNames], keyedNames, blockers };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user