Skip to content

Commit

Permalink
feat(nbstore): add awareness storage
Browse files Browse the repository at this point in the history
  • Loading branch information
EYHN committed Dec 11, 2024
1 parent 989ef84 commit 1045cee
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
43 changes: 43 additions & 0 deletions packages/common/nbstore/src/impls/idb/awareness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { share } from '../../connection';
import {
type AwarenessRecord,
AwarenessStorage,
} from '../../storage/awareness';
import { IDBConnection } from './db';

export class IndexedDBAwarenessStorage extends AwarenessStorage {
override readonly storageType = 'awareness';
override readonly connection = share(new IDBConnection(this.options));

private readonly subscriptions = new Map<
string,
Set<(update: AwarenessRecord, origin?: string) => void>
>();

private readonly cached = new Map<string, AwarenessRecord>();

override update(record: AwarenessRecord, origin?: string): Promise<void> {
const subscribers = this.subscriptions.get(record.docId);
if (subscribers) {
subscribers.forEach(callback => callback(record, origin));
}
this.cached.set(record.docId, record);
return Promise.resolve();
}

override subscribeUpdate(
id: string,
callback: (update: AwarenessRecord, origin?: string) => void
): () => void {
const subscribers = this.subscriptions.get(id) ?? new Set();
subscribers.add(callback);
this.subscriptions.set(id, subscribers);
const cached = this.cached.get(id);
if (cached) {
callback(cached);
}
return () => {
subscribers.delete(callback);
};
}
}
26 changes: 26 additions & 0 deletions packages/common/nbstore/src/storage/awareness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Storage, type StorageOptions } from './storage';

export interface AwarenessStorageOptions extends StorageOptions {}

export type AwarenessRecord = {
docId: string;
bin: Uint8Array;
};

export abstract class AwarenessStorage<
Options extends AwarenessStorageOptions = AwarenessStorageOptions,
> extends Storage<Options> {
override readonly storageType = 'awareness';

/**
* Update the awareness record.
*
* @param origin - Internal identifier to recognize the source in the "update" event. Will not be stored or transferred.
*/
abstract update(record: AwarenessRecord, origin?: string): Promise<void>;

abstract subscribeUpdate(
id: string,
callback: (update: AwarenessRecord, origin?: string) => void
): () => void;
}
2 changes: 2 additions & 0 deletions packages/common/nbstore/src/storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import EventEmitter2 from 'eventemitter2';

import type { ConnectionStatus } from '../connection';
import { type Storage, type StorageType } from '../storage';
import type { AwarenessStorage } from './awareness';
import type { BlobStorage } from './blob';
import type { DocStorage } from './doc';
import type { SyncStorage } from './sync';
Expand All @@ -20,6 +21,7 @@ export class SpaceStorage {
tryGet(type: 'blob'): BlobStorage | undefined;
tryGet(type: 'sync'): SyncStorage | undefined;
tryGet(type: 'doc'): DocStorage | undefined;
tryGet(type: 'awareness'): AwarenessStorage | undefined;
tryGet(type: StorageType) {
return this.storages.get(type);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/common/nbstore/src/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Connection } from '../connection';

export type SpaceType = 'workspace' | 'userspace';
export type StorageType = 'blob' | 'doc' | 'sync';
export type StorageType = 'blob' | 'doc' | 'sync' | 'awareness';

export interface StorageOptions {
peer: string;
Expand Down

0 comments on commit 1045cee

Please sign in to comment.