mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-19 07:17:00 +08:00
perf: use lazy load provider for IDB and SQLITE (#3351)
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
applyUpdate,
|
||||
type Doc,
|
||||
encodeStateAsUpdate,
|
||||
encodeStateVector,
|
||||
encodeStateVectorFromUpdate,
|
||||
} from 'yjs';
|
||||
|
||||
@@ -33,30 +34,30 @@ export const createLazyProvider = (
|
||||
let connected = false;
|
||||
const pendingMap = new Map<string, Uint8Array[]>(); // guid -> pending-updates
|
||||
const disposableMap = new Map<string, Set<() => void>>();
|
||||
const connectedDocs = new Set();
|
||||
const connectedDocs = new Set<string>();
|
||||
let datasourceUnsub: (() => void) | undefined;
|
||||
|
||||
async function syncDoc(doc: Doc) {
|
||||
const guid = doc.guid;
|
||||
// perf: optimize me
|
||||
const currentUpdate = encodeStateAsUpdate(doc);
|
||||
|
||||
const remoteUpdate = await datasource.queryDocState(guid, {
|
||||
stateVector: encodeStateVectorFromUpdate(currentUpdate),
|
||||
stateVector: encodeStateVector(doc),
|
||||
});
|
||||
|
||||
const updates = [currentUpdate];
|
||||
pendingMap.set(guid, []);
|
||||
|
||||
if (remoteUpdate) {
|
||||
applyUpdate(doc, remoteUpdate, selfUpdateOrigin);
|
||||
const newUpdate = encodeStateAsUpdate(
|
||||
doc,
|
||||
encodeStateVectorFromUpdate(remoteUpdate)
|
||||
);
|
||||
updates.push(newUpdate);
|
||||
await datasource.sendDocUpdate(guid, newUpdate);
|
||||
}
|
||||
|
||||
const sv = remoteUpdate
|
||||
? encodeStateVectorFromUpdate(remoteUpdate)
|
||||
: undefined;
|
||||
|
||||
// perf: optimize me
|
||||
// it is possible the doc is only in memory but not yet in the datasource
|
||||
// we need to send the whole update to the datasource
|
||||
await datasource.sendDocUpdate(guid, encodeStateAsUpdate(doc, sv));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,10 +74,7 @@ export const createLazyProvider = (
|
||||
datasource.sendDocUpdate(doc.guid, update).catch(console.error);
|
||||
};
|
||||
|
||||
const subdocLoadHandler = (event: {
|
||||
loaded: Set<Doc>;
|
||||
removed: Set<Doc>;
|
||||
}) => {
|
||||
const subdocsHandler = (event: { loaded: Set<Doc>; removed: Set<Doc> }) => {
|
||||
event.loaded.forEach(subdoc => {
|
||||
connectDoc(subdoc).catch(console.error);
|
||||
});
|
||||
@@ -86,11 +84,11 @@ export const createLazyProvider = (
|
||||
};
|
||||
|
||||
doc.on('update', updateHandler);
|
||||
doc.on('subdocs', subdocLoadHandler);
|
||||
doc.on('subdocs', subdocsHandler);
|
||||
// todo: handle destroy?
|
||||
disposables.add(() => {
|
||||
doc.off('update', updateHandler);
|
||||
doc.off('subdocs', subdocLoadHandler);
|
||||
doc.off('subdocs', subdocsHandler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -127,6 +125,7 @@ export const createLazyProvider = (
|
||||
connectedDocs.add(doc.guid);
|
||||
setupDocListener(doc);
|
||||
await syncDoc(doc);
|
||||
|
||||
await Promise.all(
|
||||
[...doc.subdocs]
|
||||
.filter(subdoc => subdoc.shouldLoad)
|
||||
@@ -150,6 +149,7 @@ export const createLazyProvider = (
|
||||
disposables.forEach(dispose => dispose());
|
||||
});
|
||||
disposableMap.clear();
|
||||
connectedDocs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,3 +12,19 @@ export function getDoc(doc: Doc, guid: string): Doc | undefined {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const saveAlert = (event: BeforeUnloadEvent) => {
|
||||
event.preventDefault();
|
||||
return (event.returnValue =
|
||||
'Data is not saved. Are you sure you want to leave?');
|
||||
};
|
||||
|
||||
export const writeOperation = async (op: Promise<unknown>) => {
|
||||
window.addEventListener('beforeunload', saveAlert, {
|
||||
capture: true,
|
||||
});
|
||||
await op;
|
||||
window.removeEventListener('beforeunload', saveAlert, {
|
||||
capture: true,
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user