170 lines
4.8 KiB
TypeScript
170 lines
4.8 KiB
TypeScript
|
|
import type * as plugins from './plugins.js';
|
||
|
|
import type { TLedgerBackend, TMigrationStatus } from './types.js';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Constructor options for SmartMigration.
|
||
|
|
*/
|
||
|
|
export interface ISmartMigrationOptions {
|
||
|
|
/** Target version for the data. Typically the app's package.json version. */
|
||
|
|
targetVersion: string;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Optional smartdata instance. Required if any step uses ctx.db / ctx.mongo,
|
||
|
|
* and required if you want a mongo-backed ledger.
|
||
|
|
*/
|
||
|
|
db?: plugins.smartdata.SmartdataDb;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Optional smartbucket Bucket. Required if any step uses ctx.bucket / ctx.s3,
|
||
|
|
* and required if you want an S3-backed ledger.
|
||
|
|
*/
|
||
|
|
bucket?: plugins.smartbucket.Bucket;
|
||
|
|
|
||
|
|
/** Logical name for this migration ledger. Defaults to "smartmigration". */
|
||
|
|
ledgerName?: string;
|
||
|
|
|
||
|
|
/** Where to persist the ledger. Defaults to "mongo" if db provided, otherwise "s3". */
|
||
|
|
ledgerBackend?: TLedgerBackend;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* For a fresh install (no ledger AND no app data), jump straight to this version
|
||
|
|
* instead of running every step from the earliest. Defaults to undefined,
|
||
|
|
* which means "run every step from earliest from-version".
|
||
|
|
*/
|
||
|
|
freshInstallVersion?: string;
|
||
|
|
|
||
|
|
/** How long (ms) to wait for a stale lock from another instance. Default 60_000. */
|
||
|
|
lockWaitMs?: number;
|
||
|
|
|
||
|
|
/** How long (ms) before this instance's own lock auto-expires. Default 600_000. */
|
||
|
|
lockTtlMs?: number;
|
||
|
|
|
||
|
|
/** If true, run() returns the plan without executing anything. Default false. */
|
||
|
|
dryRun?: boolean;
|
||
|
|
|
||
|
|
/** Custom logger. Defaults to module logger. */
|
||
|
|
logger?: plugins.smartlog.Smartlog;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Information about a single step exposed to the migration handler via ctx.step.
|
||
|
|
*/
|
||
|
|
export interface IMigrationStepInfo {
|
||
|
|
id: string;
|
||
|
|
fromVersion: string;
|
||
|
|
toVersion: string;
|
||
|
|
description?: string;
|
||
|
|
isResumable: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The context object passed into every step's `up()` handler.
|
||
|
|
*/
|
||
|
|
export interface IMigrationContext {
|
||
|
|
/** High-level smartdata instance. Present iff `db` was passed to the constructor. */
|
||
|
|
db?: plugins.smartdata.SmartdataDb;
|
||
|
|
|
||
|
|
/** High-level smartbucket Bucket. Present iff `bucket` was passed to the constructor. */
|
||
|
|
bucket?: plugins.smartbucket.Bucket;
|
||
|
|
|
||
|
|
/** Raw mongo `Db`. Present iff `db` was passed to the constructor. */
|
||
|
|
mongo?: plugins.TRawMongoDb;
|
||
|
|
|
||
|
|
/** Raw S3 client. Present iff `bucket` was passed to the constructor. */
|
||
|
|
s3?: plugins.TRawS3Client;
|
||
|
|
|
||
|
|
/** Metadata about the currently running step. */
|
||
|
|
step: IMigrationStepInfo;
|
||
|
|
|
||
|
|
/** Logger scoped to this run. */
|
||
|
|
log: plugins.smartlog.Smartlog;
|
||
|
|
|
||
|
|
/** True when run() was called with `dryRun: true`. */
|
||
|
|
isDryRun: boolean;
|
||
|
|
|
||
|
|
/** Only present when the step was marked `.resumable()`. */
|
||
|
|
checkpoint?: IMigrationCheckpoint;
|
||
|
|
|
||
|
|
/** Convenience for transactional mongo migrations. Throws if no db configured. */
|
||
|
|
startSession(): plugins.TMongoClientSession;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Per-step persistent key/value store, used by resumable migrations to
|
||
|
|
* record progress so a subsequent run can pick up where the previous one
|
||
|
|
* stopped.
|
||
|
|
*/
|
||
|
|
export interface IMigrationCheckpoint {
|
||
|
|
read<T = unknown>(key: string): Promise<T | undefined>;
|
||
|
|
write<T = unknown>(key: string, value: T): Promise<void>;
|
||
|
|
clear(): Promise<void>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The serialized form of a migration step's outcome, as stored in the ledger.
|
||
|
|
*/
|
||
|
|
export interface IMigrationLedgerEntry {
|
||
|
|
id: string;
|
||
|
|
fromVersion: string;
|
||
|
|
toVersion: string;
|
||
|
|
status: TMigrationStatus;
|
||
|
|
startedAt: string;
|
||
|
|
finishedAt: string;
|
||
|
|
durationMs: number;
|
||
|
|
error?: { message: string; stack?: string };
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Per-step result returned by run().
|
||
|
|
*/
|
||
|
|
export interface IMigrationStepResult {
|
||
|
|
id: string;
|
||
|
|
fromVersion: string;
|
||
|
|
toVersion: string;
|
||
|
|
status: TMigrationStatus;
|
||
|
|
durationMs: number;
|
||
|
|
startedAt: string;
|
||
|
|
finishedAt: string;
|
||
|
|
error?: { message: string; stack?: string };
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Result of a single call to SmartMigration.run() or .plan().
|
||
|
|
*/
|
||
|
|
export interface IMigrationRunResult {
|
||
|
|
currentVersionBefore: string | null;
|
||
|
|
currentVersionAfter: string;
|
||
|
|
targetVersion: string;
|
||
|
|
wasUpToDate: boolean;
|
||
|
|
wasFreshInstall: boolean;
|
||
|
|
stepsApplied: IMigrationStepResult[];
|
||
|
|
stepsSkipped: IMigrationStepResult[];
|
||
|
|
totalDurationMs: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The opaque definition of a registered step. Created by MigrationStepBuilder.
|
||
|
|
*/
|
||
|
|
export interface IMigrationStepDefinition {
|
||
|
|
id: string;
|
||
|
|
fromVersion: string;
|
||
|
|
toVersion: string;
|
||
|
|
description?: string;
|
||
|
|
isResumable: boolean;
|
||
|
|
handler: (ctx: IMigrationContext) => Promise<void>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Internal: the shape of the data persisted in the ledger backend.
|
||
|
|
*/
|
||
|
|
export interface ISmartMigrationLedgerData {
|
||
|
|
currentVersion: string | null;
|
||
|
|
steps: Record<string, IMigrationLedgerEntry>;
|
||
|
|
lock: {
|
||
|
|
holder: string | null;
|
||
|
|
acquiredAt: string | null;
|
||
|
|
expiresAt: string | null;
|
||
|
|
};
|
||
|
|
checkpoints: Record<string, Record<string, unknown>>;
|
||
|
|
}
|