refactor(workspace): sync doc update in background using data source (#4081)

This commit is contained in:
Alex Yang
2023-08-31 16:20:57 -05:00
committed by GitHub
parent 4091ff8e36
commit 7082937b62
7 changed files with 189 additions and 62 deletions
+38 -23
View File
@@ -1,15 +1,20 @@
import { syncDataSource } from '@affine/y-provider';
import { createIndexeddbStorage } from '@blocksuite/store';
import { pushBinary } from '@toeverything/y-indexeddb';
import {
createIndexedDBDatasource,
DEFAULT_DB_NAME,
downloadBinary,
} from '@toeverything/y-indexeddb';
import type { Doc } from 'yjs';
import { applyUpdate } from 'yjs';
import { createCloudBlobStorage } from '../blob/cloud-blob-storage';
import { downloadBinaryFromCloud } from '../providers/cloud';
import { createAffineDataSource } from '.';
import { CRUD } from './crud';
let abortController: AbortController | undefined;
const downloadRecursive = async (
const downloadRootFromIndexedDB = async (
rootGuid: string,
doc: Doc,
signal: AbortSignal
@@ -17,33 +22,43 @@ const downloadRecursive = async (
if (signal.aborted) {
return;
}
const binary = await downloadBinaryFromCloud(rootGuid, doc.guid);
if (typeof binary !== 'boolean') {
const update = new Uint8Array(binary);
if (rootGuid === doc.guid) {
// only apply the root doc
applyUpdate(doc, update, 'affine-cloud-service');
} else {
await pushBinary(doc.guid, update);
}
const update = await downloadBinary(rootGuid);
if (update !== false) {
applyUpdate(doc, update);
}
return Promise.all(
[...doc.subdocs.values()].map(subdoc =>
downloadRecursive(rootGuid, subdoc, signal)
)
).then();
};
export async function startSync() {
if (!environment.isDesktop) {
return;
}
abortController = new AbortController();
const signal = abortController.signal;
const workspaces = await CRUD.list();
const downloadCloudPromises = workspaces.map(workspace =>
downloadRecursive(workspace.id, workspace.blockSuiteWorkspace.doc, signal)
const syncDocPromises = workspaces.map(workspace =>
downloadRootFromIndexedDB(
workspace.id,
workspace.blockSuiteWorkspace.doc,
signal
)
);
await Promise.all(syncDocPromises);
const syncPromises = workspaces.map(workspace => {
const remoteDataSource = createAffineDataSource(
workspace.id,
workspace.blockSuiteWorkspace.doc,
workspace.blockSuiteWorkspace.awarenessStore.awareness
);
const indexeddbDataSource = createIndexedDBDatasource({
dbName: DEFAULT_DB_NAME,
});
return syncDataSource(
(): string[] => [
workspace.blockSuiteWorkspace.doc.guid,
...[...workspace.blockSuiteWorkspace.doc.subdocs].map(doc => doc.guid),
],
remoteDataSource,
indexeddbDataSource
);
});
const syncBlobPromises = workspaces.map(async workspace => {
const cloudBlobStorage = createCloudBlobStorage(workspace.id);
const indexeddbBlobStorage = createIndexeddbStorage(workspace.id);
@@ -88,7 +103,7 @@ export async function startSync() {
]);
});
});
await Promise.all([...downloadCloudPromises, ...syncBlobPromises]);
await Promise.all([...syncPromises, ...syncBlobPromises]);
}
export async function stopSync() {