mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
refactor: replace with data source (#4447)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import type { DatasourceDocAdapter } from '@affine/y-provider';
|
import type { DocDataSource } from '@affine/y-provider';
|
||||||
import type { Socket } from 'socket.io-client';
|
import type { Socket } from 'socket.io-client';
|
||||||
import { Manager } from 'socket.io-client';
|
import { Manager } from 'socket.io-client';
|
||||||
import {
|
import {
|
||||||
@@ -129,7 +129,7 @@ export const createAffineDataSource = (
|
|||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
} satisfies DatasourceDocAdapter & { readonly socket: Socket };
|
} satisfies DocDataSource & { readonly socket: Socket };
|
||||||
};
|
};
|
||||||
|
|
||||||
function setupAffineAwareness(
|
function setupAffineAwareness(
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import type { DocProviderCreator } from '@blocksuite/store';
|
|||||||
import { Workspace } from '@blocksuite/store';
|
import { Workspace } from '@blocksuite/store';
|
||||||
import { createBroadcastChannelProvider } from '@blocksuite/store/providers/broadcast-channel';
|
import { createBroadcastChannelProvider } from '@blocksuite/store/providers/broadcast-channel';
|
||||||
import {
|
import {
|
||||||
|
createIndexedDBDatasource,
|
||||||
createIndexedDBProvider as create,
|
createIndexedDBProvider as create,
|
||||||
downloadBinary,
|
|
||||||
} from '@toeverything/y-indexeddb';
|
} from '@toeverything/y-indexeddb';
|
||||||
import type { Doc } from 'yjs';
|
import { encodeStateVector } from 'yjs';
|
||||||
|
|
||||||
import { createAffineDataSource } from '../affine';
|
import { createAffineDataSource } from '../affine';
|
||||||
import {
|
import {
|
||||||
@@ -87,18 +87,13 @@ const createIndexedDBDownloadProvider: DocProviderCreator = (
|
|||||||
id,
|
id,
|
||||||
doc
|
doc
|
||||||
): LocalIndexedDBDownloadProvider => {
|
): LocalIndexedDBDownloadProvider => {
|
||||||
|
const datasource = createIndexedDBDatasource({});
|
||||||
let _resolve: () => void;
|
let _resolve: () => void;
|
||||||
let _reject: (error: unknown) => void;
|
let _reject: (error: unknown) => void;
|
||||||
const promise = new Promise<void>((resolve, reject) => {
|
const promise = new Promise<void>((resolve, reject) => {
|
||||||
_resolve = resolve;
|
_resolve = resolve;
|
||||||
_reject = reject;
|
_reject = reject;
|
||||||
});
|
});
|
||||||
async function downloadAndApply(doc: Doc) {
|
|
||||||
const binary = await downloadBinary(doc.guid);
|
|
||||||
if (binary) {
|
|
||||||
Y.applyUpdate(doc, binary, indexedDBDownloadOrigin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
flavour: 'local-indexeddb',
|
flavour: 'local-indexeddb',
|
||||||
@@ -111,7 +106,17 @@ const createIndexedDBDownloadProvider: DocProviderCreator = (
|
|||||||
},
|
},
|
||||||
sync: () => {
|
sync: () => {
|
||||||
logger.info('sync indexeddb provider', id);
|
logger.info('sync indexeddb provider', id);
|
||||||
downloadAndApply(doc).then(_resolve).catch(_reject);
|
datasource
|
||||||
|
.queryDocState(doc.guid, {
|
||||||
|
stateVector: encodeStateVector(doc),
|
||||||
|
})
|
||||||
|
.then(docState => {
|
||||||
|
if (docState) {
|
||||||
|
Y.applyUpdate(doc, docState.missing, indexedDBDownloadOrigin);
|
||||||
|
}
|
||||||
|
_resolve();
|
||||||
|
})
|
||||||
|
.catch(_reject);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ import type {
|
|||||||
SQLiteDBDownloadProvider,
|
SQLiteDBDownloadProvider,
|
||||||
SQLiteProvider,
|
SQLiteProvider,
|
||||||
} from '@affine/env/workspace';
|
} from '@affine/env/workspace';
|
||||||
import {
|
import { createLazyProvider, type DocDataSource } from '@affine/y-provider';
|
||||||
createLazyProvider,
|
|
||||||
type DatasourceDocAdapter,
|
|
||||||
} from '@affine/y-provider';
|
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import type { DocProviderCreator } from '@blocksuite/store';
|
import type { DocProviderCreator } from '@blocksuite/store';
|
||||||
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
|
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
|
||||||
@@ -17,7 +14,7 @@ const Y = BlockSuiteWorkspace.Y;
|
|||||||
|
|
||||||
const sqliteOrigin = 'sqlite-provider-origin';
|
const sqliteOrigin = 'sqlite-provider-origin';
|
||||||
|
|
||||||
const createDatasource = (workspaceId: string): DatasourceDocAdapter => {
|
const createDatasource = (workspaceId: string): DocDataSource => {
|
||||||
if (!window.apis?.db) {
|
if (!window.apis?.db) {
|
||||||
throw new Error('sqlite datasource is not available');
|
throw new Error('sqlite datasource is not available');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
createLazyProvider,
|
createLazyProvider,
|
||||||
type DatasourceDocAdapter,
|
type DocDataSource,
|
||||||
writeOperation,
|
writeOperation,
|
||||||
} from '@affine/y-provider';
|
} from '@affine/y-provider';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
@@ -26,10 +26,10 @@ export function setMergeCount(count: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const createIndexedDBDatasource = ({
|
export const createIndexedDBDatasource = ({
|
||||||
dbName,
|
dbName = DEFAULT_DB_NAME,
|
||||||
mergeCount,
|
mergeCount,
|
||||||
}: {
|
}: {
|
||||||
dbName: string;
|
dbName?: string;
|
||||||
mergeCount?: number;
|
mergeCount?: number;
|
||||||
}) => {
|
}) => {
|
||||||
let dbPromise: Promise<IDBPDatabase<BlockSuiteBinaryDB>> | null = null;
|
let dbPromise: Promise<IDBPDatabase<BlockSuiteBinaryDB>> | null = null;
|
||||||
@@ -99,7 +99,7 @@ export const createIndexedDBDatasource = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} satisfies DatasourceDocAdapter;
|
} satisfies DocDataSource;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...adapter,
|
...adapter,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { setTimeout } from 'node:timers/promises';
|
|||||||
import { describe, expect, test, vi } from 'vitest';
|
import { describe, expect, test, vi } from 'vitest';
|
||||||
import { applyUpdate, Doc, encodeStateAsUpdate, encodeStateVector } from 'yjs';
|
import { applyUpdate, Doc, encodeStateAsUpdate, encodeStateVector } from 'yjs';
|
||||||
|
|
||||||
import type { DatasourceDocAdapter } from '../data-source';
|
import type { DocDataSource } from '../data-source';
|
||||||
import { createLazyProvider } from '../lazy-provider';
|
import { createLazyProvider } from '../lazy-provider';
|
||||||
import { getDoc } from '../utils';
|
import { getDoc } from '../utils';
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ const createMemoryDatasource = (rootDoc: Doc) => {
|
|||||||
listeners.delete(callback);
|
listeners.delete(callback);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
} satisfies DatasourceDocAdapter;
|
} satisfies DocDataSource;
|
||||||
return {
|
return {
|
||||||
rootDoc, // expose rootDoc for testing
|
rootDoc, // expose rootDoc for testing
|
||||||
...adapter,
|
...adapter,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { applyUpdate, encodeStateAsUpdate } from 'yjs';
|
|||||||
|
|
||||||
import type { DocState } from './types';
|
import type { DocState } from './types';
|
||||||
|
|
||||||
export interface DatasourceDocAdapter {
|
export interface DocDataSource {
|
||||||
/**
|
/**
|
||||||
* request diff update from other clients
|
* request diff update from other clients
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +31,7 @@ export interface DatasourceDocAdapter {
|
|||||||
|
|
||||||
export async function syncDocFromDataSource(
|
export async function syncDocFromDataSource(
|
||||||
rootDoc: YDoc,
|
rootDoc: YDoc,
|
||||||
datasource: DatasourceDocAdapter
|
datasource: DocDataSource
|
||||||
) {
|
) {
|
||||||
const downloadDocStateRecursively = async (doc: YDoc) => {
|
const downloadDocStateRecursively = async (doc: YDoc) => {
|
||||||
const docState = await datasource.queryDocState(doc.guid);
|
const docState = await datasource.queryDocState(doc.guid);
|
||||||
@@ -49,7 +49,7 @@ export async function syncDocFromDataSource(
|
|||||||
|
|
||||||
export async function syncDataSourceFromDoc(
|
export async function syncDataSourceFromDoc(
|
||||||
rootDoc: YDoc,
|
rootDoc: YDoc,
|
||||||
datasource: DatasourceDocAdapter
|
datasource: DocDataSource
|
||||||
) {
|
) {
|
||||||
const uploadDocStateRecursively = async (doc: YDoc) => {
|
const uploadDocStateRecursively = async (doc: YDoc) => {
|
||||||
await datasource.sendDocUpdate(doc.guid, encodeStateAsUpdate(doc));
|
await datasource.sendDocUpdate(doc.guid, encodeStateAsUpdate(doc));
|
||||||
@@ -72,8 +72,8 @@ export async function syncDataSourceFromDoc(
|
|||||||
*/
|
*/
|
||||||
export async function syncDataSource(
|
export async function syncDataSource(
|
||||||
listDocGuids: () => string[],
|
listDocGuids: () => string[],
|
||||||
remoteDataSource: DatasourceDocAdapter,
|
remoteDataSource: DocDataSource,
|
||||||
localDataSource: DatasourceDocAdapter
|
localDataSource: DocDataSource
|
||||||
) {
|
) {
|
||||||
const guids = listDocGuids();
|
const guids = listDocGuids();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
encodeStateVector,
|
encodeStateVector,
|
||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
import type { DatasourceDocAdapter } from './data-source';
|
import type { DocDataSource } from './data-source';
|
||||||
import type { DataSourceAdapter } from './types';
|
import type { DataSourceAdapter } from './types';
|
||||||
import type { Status } from './types';
|
import type { Status } from './types';
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ export type DocProvider = {
|
|||||||
*/
|
*/
|
||||||
export const createLazyProvider = (
|
export const createLazyProvider = (
|
||||||
rootDoc: Doc,
|
rootDoc: Doc,
|
||||||
datasource: DatasourceDocAdapter,
|
datasource: DocDataSource,
|
||||||
options: LazyProviderOptions = {}
|
options: LazyProviderOptions = {}
|
||||||
): DocProvider & DataSourceAdapter => {
|
): DocProvider & DataSourceAdapter => {
|
||||||
let connected = false;
|
let connected = false;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DatasourceDocAdapter } from './data-source';
|
import type { DocDataSource } from './data-source';
|
||||||
|
|
||||||
export type Status =
|
export type Status =
|
||||||
| {
|
| {
|
||||||
@@ -16,7 +16,7 @@ export type Status =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface DataSourceAdapter {
|
export interface DataSourceAdapter {
|
||||||
datasource: DatasourceDocAdapter;
|
datasource: DocDataSource;
|
||||||
readonly status: Status;
|
readonly status: Status;
|
||||||
|
|
||||||
subscribeStatusChange(onStatusChange: () => void): () => void;
|
subscribeStatusChange(onStatusChange: () => void): () => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user