feat: add signal for list events

This commit is contained in:
DarkSky 2023-01-04 21:22:31 +08:00
parent ae94c901b3
commit 151a2a4311
6 changed files with 70 additions and 25 deletions

View File

@ -1,6 +1,6 @@
import assert from 'assert'; import assert from 'assert';
import { BlockSchema } from '@blocksuite/blocks/models'; import { BlockSchema } from '@blocksuite/blocks/models';
import { Workspace } from '@blocksuite/store'; import { Workspace, Signal } from '@blocksuite/store';
import { getLogger } from './index.js'; import { getLogger } from './index.js';
import { getApis, Apis } from './apis/index.js'; import { getApis, Apis } from './apis/index.js';
@ -16,6 +16,17 @@ type LoadConfig = {
config?: Record<string, any>; config?: Record<string, any>;
}; };
export type DataCenterSignals = DataCenter['signals'];
type WorkspaceItem = {
// provider id
provider: string;
// data exists locally
locally: boolean;
};
type WorkspaceLoadEvent = WorkspaceItem & {
workspace: string;
};
export class DataCenter { export class DataCenter {
private readonly _apis: Apis; private readonly _apis: Apis;
private readonly _providers = new Map<string, typeof BaseProvider>(); private readonly _providers = new Map<string, typeof BaseProvider>();
@ -23,6 +34,12 @@ export class DataCenter {
private readonly _config; private readonly _config;
private readonly _logger; private readonly _logger;
readonly signals = {
listAdd: new Signal<WorkspaceLoadEvent>(),
listRemove: new Signal<string>(),
workspaceLoaded: new Signal<WorkspaceLoadEvent>(),
};
static async init(debug: boolean): Promise<DataCenter> { static async init(debug: boolean): Promise<DataCenter> {
const dc = new DataCenter(debug); const dc = new DataCenter(debug);
dc.addProvider(AffineProvider); dc.addProvider(AffineProvider);
@ -36,6 +53,22 @@ export class DataCenter {
this._config = getKVConfigure('sys'); this._config = getKVConfigure('sys');
this._logger = getLogger('dc'); this._logger = getLogger('dc');
this._logger.enabled = debug; this._logger.enabled = debug;
this.signals.listAdd.on(e => {
this._config.set(`list:${e.workspace}`, {
provider: e.provider,
locally: e.locally,
});
});
this.signals.listRemove.on(workspace => {
this._config.delete(`list:${workspace}`);
});
this.signals.workspaceLoaded.on(e => {
this._config.set(`list:${e.workspace}`, {
provider: e.provider,
locally: e.locally,
});
});
} }
get apis(): Readonly<Apis> { get apis(): Readonly<Apis> {
@ -86,9 +119,9 @@ export class DataCenter {
await provider.init({ await provider.init({
apis: this._apis, apis: this._apis,
config, config,
globalConfig: getKVConfigure(`provider:${providerId}`),
debug: this._logger.enabled, debug: this._logger.enabled,
logger: this._logger.extend(`${Provider.id}:${id}`), logger: this._logger.extend(`${Provider.id}:${id}`),
signals: this.signals,
workspace, workspace,
}); });
await provider.initData(); await provider.initData();
@ -169,21 +202,14 @@ export class DataCenter {
* data state is also map, the key is the provider id, and the data exists locally when the value is true, otherwise it does not exist * data state is also map, the key is the provider id, and the data exists locally when the value is true, otherwise it does not exist
*/ */
async list(): Promise<Record<string, Record<string, boolean>>> { async list(): Promise<Record<string, Record<string, boolean>>> {
const lists = await Promise.all( const entries: [string, WorkspaceItem][] = await this._config.entries();
Array.from(this._providers.entries()).map(([providerId, provider]) => return entries.reduce((acc, [k, i]) => {
provider if (k.startsWith('list:')) {
.list(getKVConfigure(`provider:${providerId}`)) const key = k.slice(5);
.then(list => [providerId, list || []] as const) acc[key] = acc[key] || {};
) acc[key][i.provider] = i.locally;
);
return lists.reduce((ret, [providerId, list]) => {
for (const [item, isLocal] of list) {
const workspace = ret[item] || {};
workspace[providerId] = isLocal;
ret[item] = workspace;
} }
return ret; return acc;
}, {} as Record<string, Record<string, boolean>>); }, {} as Record<string, Record<string, boolean>>);
} }

View File

@ -8,7 +8,14 @@ const _initializeDataCenter = () => {
if (!_dataCenterInstance) { if (!_dataCenterInstance) {
_dataCenterInstance = DataCenter.init(debug); _dataCenterInstance = DataCenter.init(debug);
_dataCenterInstance.then(dc => { _dataCenterInstance.then(dc => {
(window as any).dc = dc; try {
if (window) {
(window as any).dc = dc;
}
} catch (_) {
// ignore
}
return dc; return dc;
}); });
} }

View File

@ -1,14 +1,20 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
import type { Apis, Logger, InitialParams, ConfigStore } from './index'; import type {
Apis,
DataCenterSignals,
Logger,
InitialParams,
ConfigStore,
} from './index';
export class BaseProvider { export class BaseProvider {
static id = 'base'; static id = 'base';
protected _apis!: Readonly<Apis>; protected _apis!: Readonly<Apis>;
protected _config!: Readonly<ConfigStore>; protected _config!: Readonly<ConfigStore>;
protected _globalConfig!: Readonly<ConfigStore>;
protected _logger!: Logger; protected _logger!: Logger;
protected _signals!: DataCenterSignals;
protected _workspace!: Workspace; protected _workspace!: Workspace;
constructor() { constructor() {
@ -22,8 +28,8 @@ export class BaseProvider {
async init(params: InitialParams) { async init(params: InitialParams) {
this._apis = params.apis; this._apis = params.apis;
this._config = params.config; this._config = params.config;
this._globalConfig = params.globalConfig;
this._logger = params.logger; this._logger = params.logger;
this._signals = params.signals;
this._workspace = params.workspace; this._workspace = params.workspace;
this._logger.enabled = params.debug; this._logger.enabled = params.debug;
} }

View File

@ -1,6 +1,7 @@
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
import type { Apis } from '../apis'; import type { Apis } from '../apis';
import type { DataCenterSignals } from '../datacenter';
import type { getLogger } from '../index'; import type { getLogger } from '../index';
import type { ConfigStore } from '../store'; import type { ConfigStore } from '../store';
@ -9,13 +10,13 @@ export type Logger = ReturnType<typeof getLogger>;
export type InitialParams = { export type InitialParams = {
apis: Apis; apis: Apis;
config: Readonly<ConfigStore>; config: Readonly<ConfigStore>;
globalConfig: Readonly<ConfigStore>;
debug: boolean; debug: boolean;
logger: Logger; logger: Logger;
signals: DataCenterSignals;
workspace: Workspace; workspace: Workspace;
}; };
export type { Apis, ConfigStore, Workspace }; export type { Apis, ConfigStore, DataCenterSignals, Workspace };
export type { BaseProvider } from './base.js'; export type { BaseProvider } from './base.js';
export { AffineProvider } from './affine/index.js'; export { AffineProvider } from './affine/index.js';
export { LocalProvider } from './local/index.js'; export { LocalProvider } from './local/index.js';

View File

@ -32,14 +32,19 @@ export class LocalProvider extends BaseProvider {
await this._idb.whenSynced; await this._idb.whenSynced;
this._logger('Local data loaded'); this._logger('Local data loaded');
await this._globalConfig.set(`list:${this._workspace.room}`, true); this._signals.listAdd.emit({
workspace: this._workspace.room,
provider: this.id,
locally: true,
});
} }
async clear() { async clear() {
assert(this._workspace.room);
await super.clear(); await super.clear();
await this._blobs.clear(); await this._blobs.clear();
await this._idb?.clearData(); await this._idb?.clearData();
await this._globalConfig.delete(`list:${this._workspace.room}`); this._signals.listRemove.emit(this._workspace.room);
} }
async destroy(): Promise<void> { async destroy(): Promise<void> {

View File

@ -35,7 +35,7 @@ test.describe('Workspace', () => {
await dataCenter.reload('test3', { providerId: 'affine' }); await dataCenter.reload('test3', { providerId: 'affine' });
expect(await dataCenter.list()).toStrictEqual({ expect(await dataCenter.list()).toStrictEqual({
test3: { affine: true, local: true }, test3: { affine: true },
test4: { local: true }, test4: { local: true },
test5: { local: true }, test5: { local: true },
test6: { local: true }, test6: { local: true },