| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- import type { Persistence } from 'y-socket.io/dist/server';
- import * as Y from 'yjs';
- import loggerFactory from '~/utils/logger';
- import type { MongodbPersistence } from './extended/mongodb-persistence';
- const logger = loggerFactory('growi:service:yjs:create-mongodb-persistence');
- /**
- * Based on the example by https://github.com/MaxNoetzold/y-mongodb-provider?tab=readme-ov-file#an-other-example
- * @param mdb
- * @returns
- */
- export const createMongoDBPersistence = (
- mdb: MongodbPersistence,
- ): Persistence => {
- const persistece: Persistence = {
- provider: mdb,
- bindState: async (docName, ydoc) => {
- logger.debug('bindState', { docName });
- const persistedYdoc = await mdb.getYDoc(docName);
- // get the state vector so we can just store the diffs between client and server
- const persistedStateVector = Y.encodeStateVector(persistedYdoc);
- const diff = Y.encodeStateAsUpdate(ydoc, persistedStateVector);
- // store the new data in db (if there is any: empty update is an array of 0s)
- if (
- diff.reduce(
- (previousValue, currentValue) => previousValue + currentValue,
- 0,
- ) > 0
- ) {
- mdb.storeUpdate(docName, diff);
- mdb.setTypedMeta(docName, 'updatedAt', Date.now());
- }
- // send the persisted data to clients
- Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc));
- // store updates of the document in db
- ydoc.on('update', async (update) => {
- mdb.storeUpdate(docName, update);
- mdb.setTypedMeta(docName, 'updatedAt', Date.now());
- });
- // cleanup some memory
- persistedYdoc.destroy();
- },
- writeState: async (docName) => {
- logger.debug('writeState', { docName });
- // This is called when all connections to the document are closed.
- // flush document on close to have the smallest possible database
- await mdb.flushDocument(docName);
- },
- };
- return persistece;
- };
|