feat(nbstore): improve nbstore (#9512)

This commit is contained in:
EYHN
2025-01-06 09:38:03 +00:00
parent a2563d2180
commit 46c8c4a408
103 changed files with 3337 additions and 3423 deletions
+59 -26
View File
@@ -1,17 +1,23 @@
import type { Observable } from 'rxjs';
import { combineLatest, map } from 'rxjs';
import { combineLatest, map, of } from 'rxjs';
import type { DocStorage, SyncStorage } from '../../storage';
import { DummyDocStorage } from '../../storage/dummy/doc';
import { DummySyncStorage } from '../../storage/dummy/sync';
import { MANUALLY_STOP } from '../../utils/throw-if-aborted';
import type { PeerStorageOptions } from '../types';
import { DocSyncPeer } from './peer';
export interface DocSyncState {
total: number;
syncing: number;
synced: boolean;
retrying: boolean;
errorMessage: string | null;
}
export interface DocSyncDocState {
synced: boolean;
syncing: boolean;
retrying: boolean;
errorMessage: string | null;
@@ -24,43 +30,70 @@ export interface DocSync {
}
export class DocSyncImpl implements DocSync {
private readonly peers: DocSyncPeer[] = this.remotes.map(
remote => new DocSyncPeer(this.local, this.sync, remote)
private readonly peers: DocSyncPeer[] = Object.entries(
this.storages.remotes
).map(
([peerId, remote]) =>
new DocSyncPeer(peerId, this.storages.local, this.sync, remote)
);
private abort: AbortController | null = null;
readonly state$: Observable<DocSyncState> = combineLatest(
this.peers.map(peer => peer.peerState$)
).pipe(
map(allPeers => ({
total: allPeers.reduce((acc, peer) => acc + peer.total, 0),
syncing: allPeers.reduce((acc, peer) => acc + peer.syncing, 0),
retrying: allPeers.some(peer => peer.retrying),
errorMessage:
allPeers.find(peer => peer.errorMessage)?.errorMessage ?? null,
}))
);
constructor(
readonly local: DocStorage,
readonly sync: SyncStorage,
readonly remotes: DocStorage[]
) {}
docState$(docId: string): Observable<DocSyncDocState> {
return combineLatest(this.peers.map(peer => peer.docState$(docId))).pipe(
get state$() {
return combineLatest(this.peers.map(peer => peer.peerState$)).pipe(
map(allPeers => ({
total: allPeers.reduce((acc, peer) => Math.max(acc, peer.total), 0),
syncing: allPeers.reduce((acc, peer) => Math.max(acc, peer.syncing), 0),
synced: allPeers.every(peer => peer.synced),
retrying: allPeers.some(peer => peer.retrying),
errorMessage:
allPeers.find(peer => peer.errorMessage)?.errorMessage ?? null,
retrying: allPeers.some(peer => peer.retrying),
syncing: allPeers.some(peer => peer.syncing),
}))
) as Observable<DocSyncState>;
}
constructor(
readonly storages: PeerStorageOptions<DocStorage>,
readonly sync: SyncStorage
) {}
/**
* for testing
*/
static get dummy() {
return new DocSyncImpl(
{
local: new DummyDocStorage(),
remotes: {},
},
new DummySyncStorage()
);
}
docState$(docId: string): Observable<DocSyncDocState> {
if (this.peers.length === 0) {
return of({
errorMessage: null,
retrying: false,
syncing: false,
synced: true,
});
}
return combineLatest(this.peers.map(peer => peer.docState$(docId))).pipe(
map(allPeers => {
return {
errorMessage:
allPeers.find(peer => peer.errorMessage)?.errorMessage ?? null,
retrying: allPeers.some(peer => peer.retrying),
syncing: allPeers.some(peer => peer.syncing),
synced: allPeers.every(peer => peer.synced),
};
})
);
}
start() {
if (this.abort) {
this.abort.abort();
this.abort.abort(MANUALLY_STOP);
}
const abort = new AbortController();
this.abort = abort;