From 804db1b0e439bc7bbf4fde2811e4910a16df9545 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 8 Oct 2022 18:25:49 -0400 Subject: [PATCH] Add CRDT backfill script --- .../scripts/20221008000000-backfill-crdt.ts | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 server/scripts/20221008000000-backfill-crdt.ts diff --git a/server/scripts/20221008000000-backfill-crdt.ts b/server/scripts/20221008000000-backfill-crdt.ts new file mode 100644 index 0000000000..ee0f95d4c6 --- /dev/null +++ b/server/scripts/20221008000000-backfill-crdt.ts @@ -0,0 +1,74 @@ +import "./bootstrap"; +import { updateYFragment } from "@getoutline/y-prosemirror"; +import * as Y from "yjs"; +import { parser } from "@server/editor"; +import { Document } from "@server/models"; + +const limit = 100; +const page = 0; +const teamId = process.argv[2]; + +export default async function main(exit = false) { + const work = async (page: number): Promise => { + console.log(`Backfill crdt… page ${page}`); + + if (!teamId && process.env.DEPLOYMENT === "hosted") { + throw new Error("Team ID is required"); + } + + // Retrieve all documents within set limit. + const documents = await Document.unscoped().findAll({ + attributes: ["id", "urlId", "text", "state"], + limit, + offset: page * limit, + where: { + ...(teamId ? { teamId } : {}), + state: null, + }, + order: [["createdAt", "ASC"]], + paranoid: false, + }); + + console.log(documents.length); + + for (const document of documents) { + if (document.state || !document.text) { + continue; + } + + console.log(`Writing CRDT for ${document.id}`); + + const ydoc = new Y.Doc(); + const type = ydoc.get("default", Y.XmlFragment) as Y.XmlFragment; + const doc = parser.parse(document.text); + + if (!type.doc) { + throw new Error("type.doc not found"); + } + + // apply new document to existing ydoc + updateYFragment(type.doc, type, doc, new Map()); + + const state = Y.encodeStateAsUpdate(ydoc); + document.state = Buffer.from(state); + + await document.save({ + hooks: false, + silent: true, + }); + } + + return documents.length === limit ? work(page + 1) : undefined; + }; + + await work(page); + + if (exit) { + console.log("Backfill complete"); + process.exit(0); + } +} + +if (process.env.NODE_ENV !== "test") { + main(true); +}