Archived
fix(sessiond): migrate legacy archives before startup
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
migrateLegacySessionArchive,
|
||||
type LegacySessionArchiveMigrationResult,
|
||||
} from "../sessions/sessionArchiveMigration.js";
|
||||
|
||||
export interface SessionDaemonStartupLogger {
|
||||
debug(details: Record<string, unknown>, message: string): void;
|
||||
info(details: Record<string, unknown>, message: string): void;
|
||||
warn(details: Record<string, unknown>, message: string): void;
|
||||
error(details: Record<string, unknown>, message: string): void;
|
||||
}
|
||||
|
||||
export interface SessionDaemonStartupSteps<Runtime> {
|
||||
logger: SessionDaemonStartupLogger;
|
||||
createRuntime(): Runtime;
|
||||
registerRoutes(runtime: Runtime): void;
|
||||
listen(runtime: Runtime): Promise<void>;
|
||||
migrateArchive?: () => Promise<LegacySessionArchiveMigrationResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps archive migration ahead of every archive-state consumer in sessiond.
|
||||
* A failed eligible migration stops startup so runtime writes cannot make a
|
||||
* clean retry ambiguous; mutation-free eligibility skips still start normally.
|
||||
*/
|
||||
export async function runSessionDaemonStartup<Runtime>(
|
||||
steps: SessionDaemonStartupSteps<Runtime>,
|
||||
): Promise<Runtime> {
|
||||
const result = await (steps.migrateArchive ?? migrateLegacySessionArchive)();
|
||||
reportMigrationResult(result, steps.logger);
|
||||
|
||||
if (result.status === "failed") {
|
||||
throw new Error(
|
||||
`Legacy session archive migration failed during ${result.phase}; session daemon startup stopped`,
|
||||
{ cause: result.error },
|
||||
);
|
||||
}
|
||||
|
||||
const runtime = steps.createRuntime();
|
||||
steps.registerRoutes(runtime);
|
||||
await steps.listen(runtime);
|
||||
return runtime;
|
||||
}
|
||||
|
||||
function reportMigrationResult(
|
||||
result: LegacySessionArchiveMigrationResult,
|
||||
logger: SessionDaemonStartupLogger,
|
||||
): void {
|
||||
if (result.status === "skipped") {
|
||||
if (result.reason === "inspection-failed") {
|
||||
logger.warn(
|
||||
{ err: result.error, reason: result.reason },
|
||||
"could not inspect legacy session archive migration eligibility; continuing session daemon startup without migration",
|
||||
);
|
||||
} else {
|
||||
logger.debug(
|
||||
{ reason: result.reason },
|
||||
"legacy session archive migration is not eligible; continuing session daemon startup",
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.status === "failed") {
|
||||
logger.error(
|
||||
{
|
||||
err: result.error,
|
||||
phase: result.phase,
|
||||
rollbackErrorCount: result.rollbackErrors.length,
|
||||
rollbackErrors: result.rollbackErrors,
|
||||
},
|
||||
result.rollbackErrors.length === 0
|
||||
? "legacy session archive migration failed before commit; stopping session daemon startup"
|
||||
: "legacy session archive migration failed before commit and rollback was incomplete; stopping session daemon startup",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.cleanup === "incomplete") {
|
||||
logger.warn(
|
||||
{
|
||||
archiveFileCount: result.archiveFileCount,
|
||||
cleanupErrorCount: result.cleanupErrors.length,
|
||||
cleanupErrors: result.cleanupErrors,
|
||||
},
|
||||
"legacy session archive migration committed but cleanup was incomplete; continuing with the migrated destination archive",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(
|
||||
{ archiveFileCount: result.archiveFileCount },
|
||||
"migrated legacy session archive to the configured PI_WEB_DATA_DIR",
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user