mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(nbstore): new doc sync engine (#8918)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { share } from '../../connection';
|
||||
import {
|
||||
type DocClock,
|
||||
type DocClocks,
|
||||
type DocRecord,
|
||||
DocStorage,
|
||||
@@ -14,9 +15,20 @@ export class IndexedDBDocStorage extends DocStorage {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async pushDocUpdate(update: DocUpdate) {
|
||||
const trx = this.db.transaction(['updates', 'clocks'], 'readwrite');
|
||||
private _lastTimestamp = new Date(0);
|
||||
|
||||
private generateTimestamp() {
|
||||
const timestamp = new Date();
|
||||
if (timestamp.getTime() <= this._lastTimestamp.getTime()) {
|
||||
timestamp.setTime(this._lastTimestamp.getTime() + 1);
|
||||
}
|
||||
this._lastTimestamp = timestamp;
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
override async pushDocUpdate(update: DocUpdate, origin?: string) {
|
||||
const trx = this.db.transaction(['updates', 'clocks'], 'readwrite');
|
||||
const timestamp = this.generateTimestamp();
|
||||
await trx.objectStore('updates').add({
|
||||
...update,
|
||||
createdAt: timestamp,
|
||||
@@ -24,6 +36,17 @@ export class IndexedDBDocStorage extends DocStorage {
|
||||
|
||||
await trx.objectStore('clocks').put({ docId: update.docId, timestamp });
|
||||
|
||||
this.emit(
|
||||
'update',
|
||||
{
|
||||
docId: update.docId,
|
||||
bin: update.bin,
|
||||
timestamp,
|
||||
editor: update.editor,
|
||||
},
|
||||
origin
|
||||
);
|
||||
|
||||
return { docId: update.docId, timestamp };
|
||||
}
|
||||
|
||||
@@ -72,6 +95,12 @@ export class IndexedDBDocStorage extends DocStorage {
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async getDocTimestamp(docId: string): Promise<DocClock | null> {
|
||||
const trx = this.db.transaction('clocks', 'readonly');
|
||||
|
||||
return (await trx.store.get(docId)) ?? null;
|
||||
}
|
||||
|
||||
protected override async setDocSnapshot(
|
||||
snapshot: DocRecord
|
||||
): Promise<boolean> {
|
||||
|
||||
@@ -94,6 +94,7 @@ export interface DocStorageSchema extends DBSchema {
|
||||
peer: string;
|
||||
docId: string;
|
||||
clock: Date;
|
||||
pulledClock: Date;
|
||||
pushedClock: Date;
|
||||
};
|
||||
indexes: {
|
||||
|
||||
@@ -8,7 +8,7 @@ export class IndexedDBSyncStorage extends SyncStorage {
|
||||
return this.connection.inner;
|
||||
}
|
||||
|
||||
override async getPeerClocks(peer: string) {
|
||||
override async getPeerRemoteClocks(peer: string) {
|
||||
const trx = this.db.transaction('peerClocks', 'readonly');
|
||||
|
||||
const records = await trx.store.index('peer').getAll(peer);
|
||||
@@ -19,7 +19,7 @@ export class IndexedDBSyncStorage extends SyncStorage {
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
|
||||
override async setPeerClock(peer: string, clock: DocClock) {
|
||||
override async setPeerRemoteClock(peer: string, clock: DocClock) {
|
||||
const trx = this.db.transaction('peerClocks', 'readwrite');
|
||||
const record = await trx.store.get([peer, clock.docId]);
|
||||
|
||||
@@ -28,6 +28,32 @@ export class IndexedDBSyncStorage extends SyncStorage {
|
||||
peer,
|
||||
docId: clock.docId,
|
||||
clock: clock.timestamp,
|
||||
pulledClock: record?.pulledClock ?? new Date(0),
|
||||
pushedClock: record?.pushedClock ?? new Date(0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
override async getPeerPulledRemoteClocks(peer: string) {
|
||||
const trx = this.db.transaction('peerClocks', 'readonly');
|
||||
|
||||
const records = await trx.store.index('peer').getAll(peer);
|
||||
|
||||
return records.reduce((clocks, { docId, pulledClock }) => {
|
||||
clocks[docId] = pulledClock;
|
||||
return clocks;
|
||||
}, {} as DocClocks);
|
||||
}
|
||||
override async setPeerPulledRemoteClock(peer: string, clock: DocClock) {
|
||||
const trx = this.db.transaction('peerClocks', 'readwrite');
|
||||
const record = await trx.store.get([peer, clock.docId]);
|
||||
|
||||
if (!record || record.pulledClock < clock.timestamp) {
|
||||
await trx.store.put({
|
||||
peer,
|
||||
docId: clock.docId,
|
||||
clock: record?.clock ?? new Date(0),
|
||||
pulledClock: clock.timestamp,
|
||||
pushedClock: record?.pushedClock ?? new Date(0),
|
||||
});
|
||||
}
|
||||
@@ -54,6 +80,7 @@ export class IndexedDBSyncStorage extends SyncStorage {
|
||||
docId: clock.docId,
|
||||
clock: record?.clock ?? new Date(0),
|
||||
pushedClock: clock.timestamp,
|
||||
pulledClock: record?.pulledClock ?? new Date(0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ export class IndexedDBV1DocStorage extends DocStorage {
|
||||
return {};
|
||||
}
|
||||
|
||||
override async getDocTimestamp(_docId: string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override async setDocSnapshot(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user