feat!: unified migration logic in server electron, and browser (#4079)

Co-authored-by: Mirone <Saul-Mirone@outlook.com>
This commit is contained in:
Alex Yang
2023-09-06 00:44:53 -07:00
committed by GitHub
parent 925c18300f
commit 1b6a78cd00
61 changed files with 10776 additions and 10267 deletions

View File

@@ -3,8 +3,9 @@ import {
SqliteConnection,
ValidationResult,
} from '@affine/native';
import { WorkspaceVersion } from '@toeverything/infra/blocksuite';
import { migrateToLatestDatabase } from '../db/migration';
import { migrateToLatest } from '../db/migration';
import { logger } from '../logger';
/**
@@ -20,10 +21,14 @@ export abstract class BaseSQLiteAdapter {
if (!this.db) {
const validation = await SqliteConnection.validate(this.path);
if (validation === ValidationResult.MissingVersionColumn) {
await migrateToLatestDatabase(this.path);
await migrateToLatest(this.path, WorkspaceVersion.SubDoc);
}
this.db = new SqliteConnection(this.path);
await this.db.connect();
const maxVersion = await this.db.getMaxVersion();
if (maxVersion !== WorkspaceVersion.Surface) {
await migrateToLatest(this.path, WorkspaceVersion.Surface);
}
logger.info(`[SQLiteAdapter:${this.role}]`, 'connected:', this.path);
}
return this.db;

View File

@@ -2,7 +2,10 @@ import { equal } from 'node:assert';
import { resolve } from 'node:path';
import { SqliteConnection } from '@affine/native';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { Schema } from '@blocksuite/store';
import {
forceUpgradePages,
migrateToSubdoc,
WorkspaceVersion,
} from '@toeverything/infra/blocksuite';
@@ -34,15 +37,19 @@ export const migrateToSubdocAndReplaceDatabase = async (path: string) => {
await db.close();
};
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { Schema, Workspace } from '@blocksuite/store';
import { migrateWorkspace } from '@toeverything/infra/blocksuite';
// v1 v2 -> v3
export const migrateToLatestDatabase = async (path: string) => {
// v3 -> v4
export const migrateToLatest = async (
path: string,
version: WorkspaceVersion
) => {
const connection = new SqliteConnection(path);
await connection.connect();
await connection.initVersion();
if (version === WorkspaceVersion.SubDoc) {
await connection.initVersion();
} else {
await connection.setVersion(version);
}
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
const rootDoc = new YDoc();
@@ -69,24 +76,11 @@ export const migrateToLatestDatabase = async (path: string) => {
);
};
await downloadBinary(rootDoc, true);
const result = await migrateWorkspace(WorkspaceVersion.SubDoc, {
const result = await forceUpgradePages({
getSchema: () => schema,
getCurrentRootDoc: () => Promise.resolve(rootDoc),
createWorkspace: () =>
Promise.resolve(
new Workspace({
id: nanoid(10),
schema,
blobStorages: [],
providerCreators: [],
})
),
});
equal(
typeof result,
'boolean',
'migrateWorkspace should return boolean value'
);
equal(result, true, 'migrateWorkspace should return boolean value');
const uploadBinary = async (doc: YDoc, isRoot: boolean) => {
await connection.replaceUpdates(doc.guid, [
{ docId: isRoot ? undefined : doc.guid, data: encodeStateAsUpdate(doc) },

View File

@@ -1,6 +1,7 @@
import path from 'node:path';
import { ValidationResult } from '@affine/native';
import { WorkspaceVersion } from '@toeverything/infra/blocksuite';
import type {
FakeDialogResult,
LoadDBFileResult,
@@ -14,7 +15,7 @@ import { nanoid } from 'nanoid';
import { ensureSQLiteDB } from '../db/ensure-db';
import {
copyToTemp,
migrateToLatestDatabase,
migrateToLatest,
migrateToSubdocAndReplaceDatabase,
} from '../db/migration';
import type { WorkspaceSQLiteDB } from '../db/workspace-db-adapter';
@@ -204,7 +205,7 @@ export async function loadDBFile(): Promise<LoadDBFileResult> {
if (validationResult === ValidationResult.MissingVersionColumn) {
try {
const tmpDBPath = await copyToTemp(originalPath);
await migrateToLatestDatabase(tmpDBPath);
await migrateToLatest(tmpDBPath, WorkspaceVersion.SubDoc);
originalPath = tmpDBPath;
} catch (error) {
logger.warn(
@@ -223,6 +224,24 @@ export async function loadDBFile(): Promise<LoadDBFileResult> {
return { error: 'DB_FILE_INVALID' }; // invalid db file
}
const db = new SqliteConnection(originalPath);
try {
await db.connect();
if ((await db.getMaxVersion()) === WorkspaceVersion.DatabaseV3) {
const tmpDBPath = await copyToTemp(originalPath);
await migrateToLatest(tmpDBPath, WorkspaceVersion.SubDoc);
originalPath = tmpDBPath;
}
} catch (error) {
logger.warn(
`loadDBFile, migration version column failed: ${originalPath}`,
error
);
return { error: 'DB_FILE_MIGRATION_FAILED' };
} finally {
await db.close();
}
// copy the db file to a new workspace id
const workspaceId = nanoid(10);
const internalFilePath = await getWorkspaceDBPath(workspaceId);