mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
feat: dc provider
This commit is contained in:
@@ -1,18 +1,48 @@
|
||||
import { DCProvider, MemoryProvider } from './provider.js';
|
||||
import { Doc } from 'yjs';
|
||||
|
||||
import type { BaseProvider } from './provider/index.js';
|
||||
import { MemoryProvider } from './provider/index.js';
|
||||
import { getKVConfigure } from './store.js';
|
||||
|
||||
export class DataCenter {
|
||||
private readonly _providers = new Map<string, DCProvider>();
|
||||
private readonly _providers = new Map<string, typeof BaseProvider>();
|
||||
private readonly _workspaces = new Map<string, Promise<Doc | undefined>>();
|
||||
private readonly _config;
|
||||
|
||||
static async init() {
|
||||
static async init(): Promise<DataCenter> {
|
||||
const dc = new DataCenter();
|
||||
dc.addProvider(MemoryProvider);
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
private constructor() {
|
||||
// TODO
|
||||
this._config = getKVConfigure('sys');
|
||||
}
|
||||
|
||||
addProvider<P extends DCProvider>(provider: P) {
|
||||
addProvider(provider: typeof BaseProvider) {
|
||||
this._providers.set(provider.id, provider);
|
||||
}
|
||||
|
||||
private async _initWorkspace(id: string): Promise<Doc> {
|
||||
const workspace = new Doc();
|
||||
|
||||
const providerId = await this._config.get(`workspace:${id}:provider`);
|
||||
if (this._providers.has(providerId)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const Provider = this._providers.get(providerId)!;
|
||||
const provider = new Provider();
|
||||
provider.init(getKVConfigure(id));
|
||||
}
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async getWorkspace(id: string): Promise<Doc | undefined> {
|
||||
if (!this._workspaces.has(id)) {
|
||||
const workspace = this._initWorkspace(id);
|
||||
this._workspaces.set(id, workspace);
|
||||
}
|
||||
|
||||
return this._workspaces.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { IdbInstance } from './store.js';
|
||||
|
||||
export interface DCProvider {
|
||||
id: string;
|
||||
init(config: IdbInstance<any>): void;
|
||||
}
|
||||
|
||||
export class MemoryProvider implements DCProvider {
|
||||
static readonly id = 'memory';
|
||||
private _config: IdbInstance<any> | undefined;
|
||||
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
init(config: IdbInstance<any>) {
|
||||
this._config = config;
|
||||
}
|
||||
}
|
||||
14
packages/data-center/src/datacenter/provider/base.ts
Normal file
14
packages/data-center/src/datacenter/provider/base.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { ConfigStore } from '../store.js';
|
||||
|
||||
export class BaseProvider {
|
||||
static id = 'memory';
|
||||
protected _config: ConfigStore | undefined;
|
||||
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
init(config: ConfigStore) {
|
||||
this._config = config;
|
||||
}
|
||||
}
|
||||
2
packages/data-center/src/datacenter/provider/index.ts
Normal file
2
packages/data-center/src/datacenter/provider/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { BaseProvider } from './base.js';
|
||||
export { MemoryProvider } from './memory.js';
|
||||
7
packages/data-center/src/datacenter/provider/memory.ts
Normal file
7
packages/data-center/src/datacenter/provider/memory.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { BaseProvider } from './base.js';
|
||||
|
||||
export class MemoryProvider extends BaseProvider {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { createStore, del, get, keys, set } from 'idb-keyval';
|
||||
|
||||
export type IdbInstance<T = any> = {
|
||||
export type ConfigStore<T = any> = {
|
||||
get: (key: string) => Promise<T | undefined>;
|
||||
set: (key: string, value: T) => Promise<void>;
|
||||
keys: () => Promise<string[]>;
|
||||
delete: (key: string) => Promise<void>;
|
||||
};
|
||||
|
||||
const initialIndexedDB = <T = any>(database: string): IdbInstance<T> => {
|
||||
const initialIndexedDB = <T = any>(database: string): ConfigStore<T> => {
|
||||
const store = createStore(`affine:${database}`, 'database');
|
||||
return {
|
||||
get: (key: string) => get<T>(key, store),
|
||||
@@ -17,22 +17,31 @@ const initialIndexedDB = <T = any>(database: string): IdbInstance<T> => {
|
||||
};
|
||||
};
|
||||
|
||||
const globalIndexedDB = () => {
|
||||
const scopedIndexedDB = () => {
|
||||
const idb = initialIndexedDB('global');
|
||||
const storeCache = new Map<string, Readonly<ConfigStore>>();
|
||||
|
||||
return <T = any>(scope: string): IdbInstance<T> => ({
|
||||
get: (key: string) => idb.get(`${scope}:${key}`),
|
||||
set: (key: string, value: T) => idb.set(`${scope}:${key}`, value),
|
||||
keys: () =>
|
||||
idb
|
||||
.keys()
|
||||
.then(keys =>
|
||||
keys
|
||||
.filter(k => k.startsWith(`${scope}:`))
|
||||
.map(k => k.replace(`${scope}:`, ''))
|
||||
),
|
||||
delete: (key: string) => del(`${scope}:${key}`),
|
||||
});
|
||||
return <T = any>(scope: string): Readonly<ConfigStore<T>> => {
|
||||
if (!storeCache.has(scope)) {
|
||||
const store = {
|
||||
get: (key: string) => idb.get(`${scope}:${key}`),
|
||||
set: (key: string, value: T) => idb.set(`${scope}:${key}`, value),
|
||||
keys: () =>
|
||||
idb
|
||||
.keys()
|
||||
.then(keys =>
|
||||
keys
|
||||
.filter(k => k.startsWith(`${scope}:`))
|
||||
.map(k => k.replace(`${scope}:`, ''))
|
||||
),
|
||||
delete: (key: string) => del(`${scope}:${key}`),
|
||||
};
|
||||
|
||||
storeCache.set(scope, store);
|
||||
}
|
||||
|
||||
return storeCache.get(scope) as ConfigStore<T>;
|
||||
};
|
||||
};
|
||||
|
||||
export const getKVConfigure = globalIndexedDB();
|
||||
export const getKVConfigure = scopedIndexedDB();
|
||||
|
||||
Reference in New Issue
Block a user