feat!: affine cloud support (#3813)

Co-authored-by: Hongtao Lye <codert.sn@gmail.com>
Co-authored-by: liuyi <forehalo@gmail.com>
Co-authored-by: LongYinan <lynweklm@gmail.com>
Co-authored-by: X1a0t <405028157@qq.com>
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
Co-authored-by: xiaodong zuo <53252747+zuoxiaodong0815@users.noreply.github.com>
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
Co-authored-by: danielchim <kahungchim@gmail.com>
This commit is contained in:
Alex Yang
2023-08-29 05:07:05 -05:00
committed by GitHub
parent d0145c6f38
commit 2f6c4e3696
414 changed files with 19469 additions and 7591 deletions

View File

@@ -1,7 +1,7 @@
import { setTimeout } from 'node:timers/promises';
import { describe, expect, test, vi } from 'vitest';
import { applyUpdate, Doc, encodeStateAsUpdate } from 'yjs';
import { applyUpdate, Doc, encodeStateAsUpdate, encodeStateVector } from 'yjs';
import { createLazyProvider } from '../lazy-provider';
import type { DatasourceDocAdapter } from '../types';
@@ -36,7 +36,10 @@ const createMemoryDatasource = (rootDoc: Doc) => {
if (!subdoc) {
return false;
}
return encodeStateAsUpdate(subdoc, options?.stateVector);
return {
missing: encodeStateAsUpdate(subdoc, options?.stateVector),
state: encodeStateVector(subdoc),
};
},
sendDocUpdate: async (guid, update) => {
const subdoc = getDoc(rootDoc, guid);

View File

@@ -4,7 +4,6 @@ import {
type Doc,
encodeStateAsUpdate,
encodeStateVector,
encodeStateVectorFromUpdate,
} from 'yjs';
import type { DatasourceDocAdapter, StatusAdapter } from './types';
@@ -113,20 +112,22 @@ export const createLazyProvider = (
pendingMap.set(guid, []);
if (remoteUpdate) {
applyUpdate(doc, remoteUpdate, origin);
applyUpdate(doc, remoteUpdate.missing, origin);
}
const sv = remoteUpdate
? encodeStateVectorFromUpdate(remoteUpdate)
: undefined;
if (!connected) {
return;
}
// perf: optimize me
// it is possible the doc is only in memory but not yet in the datasource
// we need to send the whole update to the datasource
await datasource.sendDocUpdate(guid, encodeStateAsUpdate(doc, sv));
await datasource.sendDocUpdate(
guid,
encodeStateAsUpdate(doc, remoteUpdate ? remoteUpdate.state : undefined)
);
doc.emit('sync', []);
}
/**
@@ -159,7 +160,11 @@ export const createLazyProvider = (
});
};
const subdocsHandler = (event: { loaded: Set<Doc>; removed: Set<Doc> }) => {
const subdocsHandler = (event: {
loaded: Set<Doc>;
removed: Set<Doc>;
added: Set<Doc>;
}) => {
event.loaded.forEach(subdoc => {
connectDoc(subdoc).catch(console.error);
});
@@ -293,6 +298,7 @@ export const createLazyProvider = (
return {
get status() {
console.log('currentStatus', currentStatus);
return currentStatus;
},
subscribeStatusChange(cb: () => void) {

View File

@@ -18,21 +18,39 @@ export interface StatusAdapter {
subscribeStatusChange(onStatusChange: () => void): () => void;
}
export interface DocState {
/**
* The missing structs of client queries with self state.
*/
missing: Uint8Array;
/**
* The full state of remote, used to prepare for diff sync.
*/
state?: Uint8Array;
}
export interface DatasourceDocAdapter extends Partial<StatusAdapter> {
// request diff update from other clients
/**
* request diff update from other clients
*/
queryDocState: (
guid: string,
options?: {
stateVector?: Uint8Array;
targetClientId?: number;
}
) => Promise<Uint8Array | false>;
) => Promise<DocState | false>;
// send update to the datasource
/**
* send update to the datasource
*/
sendDocUpdate: (guid: string, update: Uint8Array) => Promise<void>;
// listen to update from the datasource. Returns a function to unsubscribe.
// this is optional because some datasource might not support it
/**
* listen to update from the datasource. Returns a function to unsubscribe.
* this is optional because some datasource might not support it
*/
onDocUpdate?(
callback: (guid: string, update: Uint8Array) => void
): () => void;