mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
fix: unhance migration logic
This commit is contained in:
parent
a1765b647b
commit
e0d2388e95
@ -28,6 +28,7 @@ import {
|
|||||||
MigrationAction,
|
MigrationAction,
|
||||||
MigrationRunParams,
|
MigrationRunParams,
|
||||||
MigrationSuccessCallback,
|
MigrationSuccessCallback,
|
||||||
|
MigrationTrigger,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -146,23 +147,18 @@ module.exports = {
|
|||||||
}: MigrationRunParams) {
|
}: MigrationRunParams) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
if (isAutoMigrate) {
|
if (isAutoMigrate) {
|
||||||
const newVersion = await this.runFromVersion(action, version);
|
await this.runFromVersion(action, version);
|
||||||
|
|
||||||
await this.metadataService.findOrCreate({
|
|
||||||
name: 'db-version',
|
|
||||||
value: newVersion,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
await this.runAll(action);
|
await this.runAll(action);
|
||||||
this.exit();
|
this.exit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await this.runOne({ action, name });
|
await this.runOne({ action, name, trigger: MigrationTrigger.CLI });
|
||||||
this.exit();
|
this.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async runOne({ name, action }: MigrationRunParams) {
|
private async runOne({ name, action, trigger }: MigrationRunParams) {
|
||||||
// verify DB status
|
// verify DB status
|
||||||
const { exist, migrationDocument } = await this.verifyStatus({
|
const { exist, migrationDocument } = await this.verifyStatus({
|
||||||
name,
|
name,
|
||||||
@ -179,6 +175,7 @@ module.exports = {
|
|||||||
name,
|
name,
|
||||||
action,
|
action,
|
||||||
migrationDocument,
|
migrationDocument,
|
||||||
|
trigger,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.failureCallback({
|
this.failureCallback({
|
||||||
@ -216,37 +213,27 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async runFromVersion(action: MigrationAction, version: string) {
|
private async runFromVersion(action: MigrationAction, version: string) {
|
||||||
const files = await this.getDirFiles();
|
const filenames = await this.getDirFiles();
|
||||||
const migrationFiles = files
|
const versions = this.getVersionsFromFilenames(filenames);
|
||||||
.filter((fileName) => fileName.endsWith('.migration.js'))
|
const filteredVersions = versions.filter(
|
||||||
.map((fileName) => {
|
(v) => v === version || this.isNewerVersion(v, version),
|
||||||
const [migrationFileName] = fileName.split('.');
|
);
|
||||||
const [, , ...migrationVersion] = migrationFileName.split('-');
|
|
||||||
return `v${migrationVersion.join('.')}`;
|
|
||||||
})
|
|
||||||
.filter((v) => this.isNewerVersion(v, version));
|
|
||||||
|
|
||||||
let lastVersion = version;
|
let lastVersion = version;
|
||||||
for (const name of migrationFiles) {
|
|
||||||
await this.runOne({ name, action });
|
for (const version of filteredVersions) {
|
||||||
lastVersion = name;
|
await this.runOne({ name: version, action });
|
||||||
|
lastVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastVersion;
|
return lastVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async runAll(action: MigrationAction) {
|
private async runAll(action: MigrationAction) {
|
||||||
const files = await this.getDirFiles();
|
const filenames = await this.getDirFiles();
|
||||||
const migrationFiles = files
|
const versions = this.getVersionsFromFilenames(filenames);
|
||||||
.filter((fileName) => fileName.includes('migration'))
|
|
||||||
.map((fileName) => {
|
|
||||||
const [migrationFileName] = fileName.split('.');
|
|
||||||
const [, , ...migrationVersion] = migrationFileName.split('-');
|
|
||||||
return `v${migrationVersion.join('.')}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const name of migrationFiles) {
|
for (const version of versions) {
|
||||||
await this.runOne({ name, action });
|
await this.runOne({ name: version, action });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,6 +272,16 @@ module.exports = {
|
|||||||
return migrationName;
|
return migrationName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getVersionsFromFilenames(filenames: string[]) {
|
||||||
|
return filenames
|
||||||
|
.filter((fileName) => fileName.endsWith('.migration.js'))
|
||||||
|
.map((filename: string) => {
|
||||||
|
const [migrationFileName] = filename.split('.');
|
||||||
|
const [, , ...migrationVersion] = migrationFileName.split('-');
|
||||||
|
return `v${migrationVersion.join('.')}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async findMigrationFileByName(name: string): Promise<string | null> {
|
async findMigrationFileByName(name: string): Promise<string | null> {
|
||||||
const files = await this.getMigrationFiles();
|
const files = await this.getMigrationFiles();
|
||||||
return (
|
return (
|
||||||
@ -342,10 +339,19 @@ module.exports = {
|
|||||||
name,
|
name,
|
||||||
action,
|
action,
|
||||||
migrationDocument,
|
migrationDocument,
|
||||||
|
trigger,
|
||||||
}: MigrationSuccessCallback) {
|
}: MigrationSuccessCallback) {
|
||||||
await this.updateStatus({ name, action, migrationDocument });
|
await this.updateStatus({ name, action, migrationDocument });
|
||||||
const migrationDisplayName = `${name} [${action}]`;
|
const migrationDisplayName = `${name} [${action}]`;
|
||||||
this.logger.log(`"${migrationDisplayName}" migration done`);
|
this.logger.log(`"${migrationDisplayName}" migration done`);
|
||||||
|
if (trigger === MigrationTrigger.CLI) {
|
||||||
|
const result = await this.metadataService.createOrUpdate({
|
||||||
|
name: 'db-version',
|
||||||
|
value: name,
|
||||||
|
});
|
||||||
|
const operation = result ? 'updated' : 'created';
|
||||||
|
this.logger.log(`db-version metadata ${operation} "${name}"`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private failureCallback({ name, action }: MigrationRunParams) {
|
private failureCallback({ name, action }: MigrationRunParams) {
|
||||||
|
@ -13,15 +13,26 @@ enum MigrationAction {
|
|||||||
DOWN = 'down',
|
DOWN = 'down',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MigrationTrigger {
|
||||||
|
CLI = 'cli',
|
||||||
|
PROGRAM = 'program',
|
||||||
|
}
|
||||||
|
|
||||||
interface MigrationRunParams {
|
interface MigrationRunParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
action: MigrationAction;
|
action: MigrationAction;
|
||||||
version?: string;
|
version?: string;
|
||||||
isAutoMigrate?: boolean;
|
isAutoMigrate?: boolean;
|
||||||
|
trigger?: MigrationTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MigrationSuccessCallback extends MigrationRunParams {
|
interface MigrationSuccessCallback extends MigrationRunParams {
|
||||||
migrationDocument: MigrationDocument;
|
migrationDocument: MigrationDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { MigrationAction, MigrationRunParams, MigrationSuccessCallback };
|
export {
|
||||||
|
MigrationAction,
|
||||||
|
MigrationRunParams,
|
||||||
|
MigrationSuccessCallback,
|
||||||
|
MigrationTrigger,
|
||||||
|
};
|
||||||
|
@ -19,18 +19,10 @@ export class MetadataService {
|
|||||||
private readonly metadataModel: Model<Metadata>,
|
private readonly metadataModel: Model<Metadata>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createMetadata(dto: Partial<Metadata>) {
|
async createOrUpdate(dto: Metadata) {
|
||||||
return await this.metadataModel.create(dto);
|
return await this.metadataModel.findOneAndUpdate({ name: dto.name }, dto, {
|
||||||
}
|
upsert: true,
|
||||||
|
});
|
||||||
async findOrCreate(dto: Partial<Metadata>) {
|
|
||||||
const metadata = await this.metadataModel.findOne({ name: dto.name });
|
|
||||||
|
|
||||||
if (metadata) {
|
|
||||||
await this.setMetadata(dto.name, dto.value);
|
|
||||||
} else {
|
|
||||||
await this.createMetadata(dto);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMetadata(name: string) {
|
async getMetadata(name: string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user