feat(nbstore): add nbstore worker (#9185)

This commit is contained in:
EYHN
2024-12-20 08:01:23 +00:00
parent 30200ff86d
commit cbaf35df0b
51 changed files with 1144 additions and 501 deletions
@@ -1,9 +1,6 @@
import { nanoid } from 'nanoid';
import {
type AwarenessRecord,
AwarenessStorage,
} from '../../storage/awareness';
import { type AwarenessRecord, AwarenessStorageBase } from '../../storage';
import { BroadcastChannelConnection } from './channel';
type ChannelMessage =
@@ -19,13 +16,13 @@ type ChannelMessage =
collectId: string;
}
| {
type: 'awareness-collect-fallback';
type: 'awareness-collect-feedback';
docId: string;
bin: Uint8Array;
collectId: string;
};
export class BroadcastChannelAwarenessStorage extends AwarenessStorage {
export class BroadcastChannelAwarenessStorage extends AwarenessStorageBase {
override readonly storageType = 'awareness';
override readonly connection = new BroadcastChannelConnection(this.options);
get channel() {
@@ -36,7 +33,7 @@ export class BroadcastChannelAwarenessStorage extends AwarenessStorage {
string,
Set<{
onUpdate: (update: AwarenessRecord, origin?: string) => void;
onCollect: () => AwarenessRecord;
onCollect: () => Promise<AwarenessRecord | null>;
}>
>();
@@ -57,12 +54,20 @@ export class BroadcastChannelAwarenessStorage extends AwarenessStorage {
override subscribeUpdate(
id: string,
onUpdate: (update: AwarenessRecord, origin?: string) => void,
onCollect: () => AwarenessRecord
onCollect: () => Promise<AwarenessRecord | null>
): () => void {
const subscribers = this.subscriptions.get(id) ?? new Set();
subscribers.forEach(subscriber => {
const fallback = subscriber.onCollect();
onUpdate(fallback);
subscriber
.onCollect()
.then(awareness => {
if (awareness) {
onUpdate(awareness);
}
})
.catch(error => {
console.error('error in on collect awareness', error);
});
});
const collectUniqueId = nanoid();
@@ -84,18 +89,23 @@ export class BroadcastChannelAwarenessStorage extends AwarenessStorage {
message.data.type === 'awareness-collect' &&
message.data.docId === id
) {
const fallback = onCollect();
if (fallback) {
this.channel.postMessage({
type: 'awareness-collect-fallback',
docId: message.data.docId,
bin: fallback.bin,
collectId: collectUniqueId,
} satisfies ChannelMessage);
}
onCollect()
.then(awareness => {
if (awareness) {
this.channel.postMessage({
type: 'awareness-collect-feedback',
docId: message.data.docId,
bin: awareness.bin,
collectId: collectUniqueId,
} satisfies ChannelMessage);
}
})
.catch(error => {
console.error('error in on collect awareness', error);
});
}
if (
message.data.type === 'awareness-collect-fallback' &&
message.data.type === 'awareness-collect-feedback' &&
message.data.docId === id &&
message.data.collectId === collectUniqueId
) {
@@ -1,7 +1,7 @@
import { Connection } from '../../connection';
import { AutoReconnectConnection } from '../../connection';
import type { StorageOptions } from '../../storage';
export class BroadcastChannelConnection extends Connection<BroadcastChannel> {
export class BroadcastChannelConnection extends AutoReconnectConnection<BroadcastChannel> {
readonly channelName = `channel:${this.opts.peer}:${this.opts.type}:${this.opts.id}`;
constructor(private readonly opts: StorageOptions) {