create-mongodb-persistence.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import type { Persistence } from 'y-socket.io/dist/server';
  2. import * as Y from 'yjs';
  3. import loggerFactory from '~/utils/logger';
  4. import type { MongodbPersistence } from './extended/mongodb-persistence';
  5. const logger = loggerFactory('growi:service:yjs:create-mongodb-persistence');
  6. /**
  7. * Based on the example by https://github.com/MaxNoetzold/y-mongodb-provider?tab=readme-ov-file#an-other-example
  8. * @param mdb
  9. * @returns
  10. */
  11. export const createMongoDBPersistence = (mdb: MongodbPersistence): Persistence => {
  12. const persistece: Persistence = {
  13. provider: mdb,
  14. bindState: async(docName, ydoc) => {
  15. logger.debug('bindState', { docName });
  16. const persistedYdoc = await mdb.getYDoc(docName);
  17. // get the state vector so we can just store the diffs between client and server
  18. const persistedStateVector = Y.encodeStateVector(persistedYdoc);
  19. const diff = Y.encodeStateAsUpdate(ydoc, persistedStateVector);
  20. // store the new data in db (if there is any: empty update is an array of 0s)
  21. if (diff.reduce((previousValue, currentValue) => previousValue + currentValue, 0) > 0) {
  22. mdb.storeUpdate(docName, diff);
  23. mdb.setTypedMeta(docName, 'updatedAt', Date.now());
  24. }
  25. // send the persisted data to clients
  26. Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc));
  27. // store updates of the document in db
  28. ydoc.on('update', async(update) => {
  29. mdb.storeUpdate(docName, update);
  30. mdb.setTypedMeta(docName, 'updatedAt', Date.now());
  31. });
  32. // cleanup some memory
  33. persistedYdoc.destroy();
  34. },
  35. writeState: async(docName) => {
  36. logger.debug('writeState', { docName });
  37. // This is called when all connections to the document are closed.
  38. // flush document on close to have the smallest possible database
  39. await mdb.flushDocument(docName);
  40. },
  41. };
  42. return persistece;
  43. };