176 lines
10 KiB
TypeScript
176 lines
10 KiB
TypeScript
export interface FleetSettings {
|
|
provisioningKeepDays: number;
|
|
actionKeepDays: number;
|
|
failureKeepDays: number;
|
|
maintenanceKeepDays: number;
|
|
recoveryKeepDays: number;
|
|
hostResourceKeepDays: number;
|
|
instanceResourceKeepDays: number;
|
|
metricsKeepDays: number;
|
|
telemetryKeepDays: number;
|
|
telemetryMaxPerServer: number;
|
|
telemetryMaxTotal: number;
|
|
matchKeepDays: number;
|
|
betaKeepDays: number;
|
|
fileContentKeepDays: number;
|
|
payloadKeepDays: number;
|
|
versionKeepDays: number;
|
|
versionKeepCount: number;
|
|
gameFileGraceDays: number;
|
|
gameFileKeepCount: number;
|
|
uploadKeepDays: number;
|
|
auditKeepDays: number;
|
|
historyKeepCount: number;
|
|
|
|
deployKeepDays: number;
|
|
observationKeepDays: number;
|
|
restartConcurrency: number;
|
|
createConcurrency: number;
|
|
destroyConcurrency: number;
|
|
restartConcurrencyPerHost: number;
|
|
createConcurrencyPerHost: number;
|
|
destroyConcurrencyPerHost: number;
|
|
lifecycleConcurrency: number;
|
|
rebuildConcurrency: number;
|
|
preparationConcurrency: number;
|
|
|
|
}
|
|
|
|
export const defaultFleetSettings: FleetSettings = {
|
|
provisioningKeepDays: 0,
|
|
actionKeepDays: 0,
|
|
failureKeepDays: 0,
|
|
maintenanceKeepDays: 30,
|
|
recoveryKeepDays: 0,
|
|
hostResourceKeepDays: 7,
|
|
instanceResourceKeepDays: 1,
|
|
metricsKeepDays: 31,
|
|
telemetryKeepDays: 7,
|
|
telemetryMaxPerServer: 200,
|
|
telemetryMaxTotal: 10000,
|
|
matchKeepDays: 0,
|
|
betaKeepDays: 0,
|
|
fileContentKeepDays: 30,
|
|
payloadKeepDays: 30,
|
|
versionKeepDays: 0,
|
|
versionKeepCount: 0,
|
|
gameFileGraceDays: 0,
|
|
gameFileKeepCount: 1,
|
|
uploadKeepDays: 0,
|
|
auditKeepDays: 0,
|
|
historyKeepCount: 0,
|
|
|
|
deployKeepDays: 7,
|
|
observationKeepDays: 1,
|
|
restartConcurrency: 1,
|
|
createConcurrency: 1,
|
|
destroyConcurrency: 1,
|
|
restartConcurrencyPerHost: 0,
|
|
createConcurrencyPerHost: 0,
|
|
destroyConcurrencyPerHost: 0,
|
|
lifecycleConcurrency: 0,
|
|
rebuildConcurrency: 0,
|
|
preparationConcurrency: 0,
|
|
};
|
|
|
|
export const fleetSettingLabels: Record<keyof FleetSettings, string> = {
|
|
provisioningKeepDays: 'Provisioning history retention',
|
|
actionKeepDays: 'Action operation history retention',
|
|
failureKeepDays: 'Resolved failure history retention',
|
|
maintenanceKeepDays: 'Maintenance history retention',
|
|
recoveryKeepDays: 'Resolved recovery incident retention',
|
|
hostResourceKeepDays: 'Host resource history retention',
|
|
instanceResourceKeepDays: 'Instance resource sample retention',
|
|
metricsKeepDays: 'Fleet metrics history retention',
|
|
telemetryKeepDays: 'Telemetry diagnostic history retention',
|
|
telemetryMaxPerServer: 'Maximum telemetry records per server',
|
|
telemetryMaxTotal: 'Maximum telemetry records overall',
|
|
matchKeepDays: 'Match history retention',
|
|
betaKeepDays: 'Completed beta history retention',
|
|
fileContentKeepDays: 'File diffs and rollback snapshot retention',
|
|
payloadKeepDays: 'Launch and command file retention',
|
|
versionKeepDays: 'Unused artifact version retention',
|
|
versionKeepCount: 'Minimum artifact versions to keep',
|
|
gameFileGraceDays: 'Unused game-file grace period',
|
|
gameFileKeepCount: 'Minimum game-file versions to keep',
|
|
uploadKeepDays: 'Abandoned upload retention',
|
|
auditKeepDays: 'Authentication audit history retention',
|
|
historyKeepCount: 'Minimum history records to keep',
|
|
|
|
deployKeepDays: 'Campaign history retention',
|
|
observationKeepDays: 'Routine operation history retention',
|
|
restartConcurrency: 'Concurrent restarts',
|
|
createConcurrency: 'Concurrent server startups',
|
|
destroyConcurrency: 'Concurrent server destructions',
|
|
restartConcurrencyPerHost: 'Concurrent restarts per host',
|
|
createConcurrencyPerHost: 'Concurrent startups per host',
|
|
destroyConcurrencyPerHost: 'Concurrent destructions per host',
|
|
lifecycleConcurrency: 'Combined lifecycle limit',
|
|
rebuildConcurrency: 'Concurrent rebuilds',
|
|
preparationConcurrency: 'Hosts preparing game files simultaneously',
|
|
|
|
};
|
|
|
|
export function validateFleetSettings(input: unknown): FleetSettings {
|
|
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new Error('Provide fleet settings.');
|
|
const values = input as Record<string, unknown>;
|
|
for (const key of Object.keys(values)) {
|
|
if (!Object.hasOwn(defaultFleetSettings, key)) throw new Error(`Unknown setting: ${key}`);
|
|
}
|
|
for (const key of Object.keys(defaultFleetSettings) as (keyof FleetSettings)[]) {
|
|
const value = values[key];
|
|
const minimum = settingMinimum(key);
|
|
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum) {
|
|
throw new Error(`${fleetSettingLabels[key]} must be ${minimum === 0 ? 'zero or a positive whole number' : 'a positive whole number'}.`);
|
|
}
|
|
if (key.endsWith('Days') && value > 36500) {
|
|
throw new Error(`${fleetSettingLabels[key]} must be at most 36500 days.`);
|
|
}
|
|
}
|
|
return Object.fromEntries(Object.keys(defaultFleetSettings).map(key => [key, values[key]])) as unknown as FleetSettings;
|
|
}
|
|
|
|
export const additionalConcurrencyKeys: (keyof FleetSettings)[] = ["restartConcurrencyPerHost", "createConcurrencyPerHost", "destroyConcurrencyPerHost", "lifecycleConcurrency", "rebuildConcurrency", "preparationConcurrency"];
|
|
export const concurrencyKeys: (keyof FleetSettings)[] = ['restartConcurrency', 'createConcurrency', 'destroyConcurrency', ...additionalConcurrencyKeys];
|
|
export const retentionKeys: (keyof FleetSettings)[] = ['deployKeepDays', 'observationKeepDays', 'provisioningKeepDays', 'actionKeepDays', 'failureKeepDays', 'maintenanceKeepDays', 'recoveryKeepDays', 'hostResourceKeepDays', 'instanceResourceKeepDays', 'metricsKeepDays', 'telemetryKeepDays', 'telemetryMaxPerServer', 'telemetryMaxTotal', 'matchKeepDays', 'betaKeepDays', 'fileContentKeepDays', 'payloadKeepDays', 'versionKeepDays', 'versionKeepCount', 'gameFileGraceDays', 'gameFileKeepCount', 'uploadKeepDays', 'auditKeepDays', 'historyKeepCount'];
|
|
export function settingMinimum(key: keyof FleetSettings): number {
|
|
return ['restartConcurrency','createConcurrency','destroyConcurrency','gameFileKeepCount'].includes(key) ? 1 : 0;
|
|
}
|
|
|
|
export const settingHelp: Partial<Record<keyof FleetSettings, string>> = {
|
|
provisioningKeepDays: 'Completed lifecycle history. Recovery, source workflows and cancellation dependencies remain protected.',
|
|
actionKeepDays: 'Completed agent actions. Referenced commands and retry evidence remain protected. Expired actions keep compact receipts to prevent duplicate execution.',
|
|
failureKeepDays: 'Explicitly resolved failed operations and campaigns, measured from resolution. Unresolved failures remain protected.',
|
|
maintenanceKeepDays: 'Finished non-update maintenance. Update attempts remain durable to prevent duplicate automatic retries.',
|
|
recoveryKeepDays: 'Resolved watchdog incidents with no unfinished recovery. Dismissed incidents remain as suppression evidence.',
|
|
hostResourceKeepDays: 'Host CPU and memory history.',
|
|
instanceResourceKeepDays: 'Minute resource samples. Capacity learning continues to use its independent 24-hour window.',
|
|
metricsKeepDays: 'Historical fleet occupancy and utilization samples.',
|
|
telemetryKeepDays: 'Raw received telemetry diagnostics. Independent of saved matches. Count limits also apply.',
|
|
telemetryMaxPerServer: 'Count cap per server, in addition to the age limit. 0 disables this count cap.',
|
|
telemetryMaxTotal: 'Fleet-wide count cap for telemetry diagnostics. 0 disables this count cap.',
|
|
matchKeepDays: 'Completed and interrupted matches and player details. Expiry changes leaderboards and player totals; no lifetime aggregates are preserved.',
|
|
betaKeepDays: 'Closed betas, revisions and test evidence, after linked campaigns and recovery work no longer need them.',
|
|
fileContentKeepDays: 'Expired campaign file bodies are removed while summaries remain. Rollback becomes unavailable for those campaigns. Active beta snapshots remain protected.',
|
|
payloadKeepDays: 'Expire file bodies in completed launch recipes, commands and receipts while keeping their history. Unfinished work and protected records keep their files. 0 keeps files indefinitely.',
|
|
versionKeepDays: 'Unused script, plugin, configuration and baseline versions. Current and referenced versions are always protected.',
|
|
versionKeepCount: 'Keep at least this many recent versions per artifact. With no age expiry, a positive count removes older unused versions.',
|
|
gameFileGraceDays: 'Delay removal after a version becomes superseded. Latest files, referenced versions and offline host copies remain protected. 0 adds no delay.',
|
|
gameFileKeepCount: 'Keep this many recent published versions per game, in addition to every referenced or protected version.',
|
|
uploadKeepDays: 'Remove incomplete browser uploads after this many days without activity. Active transfers and publication are protected.',
|
|
auditKeepDays: 'Recorded authentication and account-administration events.',
|
|
historyKeepCount: 'Keep at least this many recent records per history category. Does not apply to metrics, resource samples, telemetry count caps or game-file storage.',
|
|
|
|
restartConcurrency: 'Fleet recovery slots stay occupied until container and game health are verified.',
|
|
createConcurrency: 'Fleet startup slots cover creation and rebuilds through health and selected-map verification.',
|
|
destroyConcurrency: 'Fleet removals hold capacity until teardown and cleanup finish.',
|
|
restartConcurrencyPerHost: 'Additional recovery limit on each host, including starts and rebuilds.',
|
|
createConcurrencyPerHost: 'Additional startup limit on each host, including rebuilds.',
|
|
destroyConcurrencyPerHost: 'Additional removal limit on each host, including migration source removal.',
|
|
lifecycleConcurrency: 'Combined fleet limit for creates, starts, stops, restarts, rebuilds and destructions. Each workflow counts once.',
|
|
rebuildConcurrency: 'Additional fleet limit for rebuilds, including host drain migrations.',
|
|
preparationConcurrency: 'Maximum hosts downloading or verifying game files at once. Interrupted transfers keep their slot until reconciled.',
|
|
deployKeepDays: 'Eligible campaign records and file diffs. Pending, unresolved failed, held and recovery-linked campaigns are protected.',
|
|
observationKeepDays: 'Successful monitoring and file-read records. Failures and actions are retained. 0 keeps records indefinitely.'
|
|
};
|