fix(core): implement editor timeout and report error from boundary (#5105) (#5151)

fix(core): implement editor timeout and report error from boundary (#5105)

ci: add sentry env when frontend assets build (#5131)

fix(core): expose catched editor load error (#5133)

fix(infra): use blocksuite api to check compatibility (#5137)

fix(infra): compatibility logic follow blocksuite (#5143)

fix(core): rerender error boundary when route change and improve sentry report (#5147)
This commit is contained in:
Joooye_34
2023-12-01 07:25:08 +00:00
parent 99f98fb9d3
commit eb7d293aaa
42 changed files with 791 additions and 342 deletions

View File

@@ -4,6 +4,10 @@ import type { createStore, WritableAtom } from 'jotai/vanilla';
import { nanoid } from 'nanoid';
import { migratePages } from '../migration/blocksuite';
import {
checkWorkspaceCompatibility,
MigrationPoint,
} from '../migration/workspace';
export async function initEmptyPage(page: Page, title?: string) {
await page.load(() => {
@@ -244,46 +248,48 @@ export async function buildShowcaseWorkspace(
{} as Record<string, string>
);
});
await Promise.all(
data.map(async ([id, promise, newId]) => {
const { default: template } = await promise;
let json = JSON.stringify(template);
Object.entries(idMap).forEach(([oldId, newId]) => {
json = json.replaceAll(oldId, newId);
});
json = JSON.parse(json);
await workspace
.importPageSnapshot(structuredClone(json), newId)
.catch(error => {
console.error('error importing page', id, error);
});
const page = workspace.getPage(newId);
assertExists(page);
await page.load();
workspace.schema.upgradePage(
0,
{
'affine:note': 1,
'affine:bookmark': 1,
'affine:database': 2,
'affine:divider': 1,
'affine:image': 1,
'affine:list': 1,
'affine:code': 1,
'affine:page': 2,
'affine:paragraph': 1,
'affine:surface': 3,
},
page.spaceDoc
);
// The showcase building will create multiple pages once, and may skip the version writing.
// https://github.com/toeverything/blocksuite/blob/master/packages/store/src/workspace/page.ts#L662
if (!workspace.meta.blockVersions) {
await migratePages(workspace.doc, workspace.schema);
}
})
);
// Import page one by one to prevent workspace meta race condition problem.
for (const [id, promise, newId] of data) {
const { default: template } = await promise;
let json = JSON.stringify(template);
Object.entries(idMap).forEach(([oldId, newId]) => {
json = json.replaceAll(oldId, newId);
});
json = JSON.parse(json);
await workspace
.importPageSnapshot(structuredClone(json), newId)
.catch(error => {
console.error('error importing page', id, error);
});
const page = workspace.getPage(newId);
assertExists(page);
await page.load();
workspace.schema.upgradePage(
0,
{
'affine:note': 1,
'affine:bookmark': 1,
'affine:database': 2,
'affine:divider': 1,
'affine:image': 1,
'affine:list': 1,
'affine:code': 1,
'affine:page': 2,
'affine:paragraph': 1,
'affine:surface': 3,
},
page.spaceDoc
);
}
// The showcase building will create multiple pages once, and may skip the version writing.
// https://github.com/toeverything/blocksuite/blob/master/packages/store/src/workspace/page.ts#L662
const compatibilityResult = checkWorkspaceCompatibility(workspace);
if (compatibilityResult === MigrationPoint.BlockVersion) {
await migratePages(workspace.doc, workspace.schema);
}
Object.entries(pageMetas).forEach(([oldId, meta]) => {
const newId = idMap[oldId];
workspace.setPageMeta(newId, meta);

View File

@@ -20,13 +20,18 @@ export async function migratePages(
const meta = rootDoc.getMap('meta') as YMap<unknown>;
const versions = meta.get('blockVersions') as YMap<number>;
const oldVersions = versions?.toJSON() ?? {};
spaces.forEach((space: YDoc) => {
try {
schema.upgradePage(0, oldVersions, space);
} catch (e) {
console.error(`page ${space.guid} upgrade failed`, e);
}
schema.upgradePage(0, oldVersions, space);
});
schema.upgradeWorkspace(rootDoc);
// Hard code to upgrade page version to 2.
// Let e2e to ensure the data version is correct.
const pageVersion = meta.get('pageVersion');
if (typeof pageVersion !== 'number' || pageVersion < 2) {
meta.set('pageVersion', 2);
}
const newVersions = getLatestVersions(schema);
meta.set('blockVersions', new YMap(Object.entries(newVersions)));

View File

@@ -43,3 +43,25 @@ export function guidCompatibilityFix(rootDoc: YDoc) {
});
return changed;
}
/**
* Hard code to fix workspace version to be compatible with legacy data.
* Let e2e to ensure the data version is correct.
*/
export function fixWorkspaceVersion(rootDoc: YDoc) {
const meta = rootDoc.getMap('meta') as YMap<unknown>;
/**
* It doesn't matter to upgrade workspace version from 1 or undefined to 2.
* Blocksuite just set the value, do nothing else.
*/
const workspaceVersion = meta.get('workspaceVersion');
if (typeof workspaceVersion !== 'number' || workspaceVersion < 2) {
meta.set('workspaceVersion', 2);
const pageVersion = meta.get('pageVersion');
if (typeof pageVersion !== 'number') {
meta.set('pageVersion', 1);
}
}
}

View File

@@ -58,15 +58,25 @@ export function checkWorkspaceCompatibility(
return MigrationPoint.SubDoc;
}
// Sometimes, blocksuite will not write blockVersions to meta.
// Just fix it when user open the workspace.
const blockVersions = workspace.meta.blockVersions;
if (!blockVersions) {
const hasVersion = workspace.meta.hasVersion;
if (!hasVersion) {
return MigrationPoint.BlockVersion;
}
// TODO: Catch compatibility error from blocksuite to show upgrade page.
// Temporarily follow the check logic of blocksuite.
if ((workspace.meta.pages?.length ?? 0) <= 1) {
try {
workspace.meta.validateVersion(workspace);
} catch (e) {
console.info('validateVersion error', e);
return MigrationPoint.BlockVersion;
}
}
// From v2, we depend on blocksuite to check and migrate data.
for (const [flavour, version] of Object.entries(blockVersions)) {
const blockVersions = workspace.meta.blockVersions;
for (const [flavour, version] of Object.entries(blockVersions ?? {})) {
const schema = workspace.schema.flavourSchemaMap.get(flavour);
if (schema?.version !== version) {
return MigrationPoint.BlockVersion;