Skip to content

Commit

Permalink
Disconnect crdt-store from previous document when changing boards
Browse files Browse the repository at this point in the history
  • Loading branch information
raimohanska committed Mar 11, 2024
1 parent a292a8b commit 081d8ff
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
1 change: 1 addition & 0 deletions frontend/src/store/board-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ export function BoardStore(
const localBoardItemEvents = uiEvents.pipe(L.filter(isPersistableBoardItemEvent, globalScope))

const crdtStore = CRDTStore(
L.view(state, (s) => s.board?.id),
L.view(state, (s) => s.status === "online"),
localBoardItemEvents,
getWebSocketRootUrl,
Expand Down
58 changes: 41 additions & 17 deletions frontend/src/store/crdt-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ function BoardCRDT(
return getCRDTField(doc, itemId, fieldName)
}

localBoardItemEvents.pipe(L.filter((e) => e.boardId === boardId)).forEach((event) => {
if (event.action === "item.add") {
importItemsIntoCRDT(doc, event.items, { fallbackToText: true })
}
})

function augmentItems(items: Item[]): Item[] {
return augmentItemsWithCRDT(doc, items)
}
Expand All @@ -60,50 +54,78 @@ function BoardCRDT(
WebSocketPolyfill,
})

online.onChange((c) => (c ? provider.connect() : provider.disconnect()))
const disconnected = L.bus()
online.pipe(L.changes, L.takeUntil(disconnected)).forEach((c) => (c ? provider.connect() : provider.disconnect()))

localBoardItemEvents
.pipe(
L.takeUntil(disconnected),
L.filter((e) => e.boardId === boardId),
)
.forEach((event) => {
if (event.action === "item.add") {
importItemsIntoCRDT(doc, event.items, { fallbackToText: true })
}
})

provider.on("status", (event: any) => {
console.log("YJS Provider status", event.status)
console.log("YJS Provider status", boardId, event.status)
})

function disconnect() {
console.log("Disconnecting YJS provider for board", boardId)
provider.destroy()
}

return {
boardId,
doc,
getField,
augmentItems,
disconnect,
awareness: provider.awareness,
}
}

export type CRDTStore = ReturnType<typeof CRDTStore>

export function CRDTStore(
currentBoardId: L.Property<Id | undefined>,
online: L.Property<boolean>,
localBoardItemEvents: L.EventStream<PersistableBoardItemEvent>,
getSocketRoot: () => string = getWebSocketRootUrl,
WebSocketPolyfill: WebSocketPolyfill = WebSocket as any,
) {
const boards = new Map<Id, BoardCRDT>()
let boardCrdt: BoardCRDT | undefined = undefined

currentBoardId.forEach((boardId) => {
if (boardCrdt && boardCrdt.boardId !== boardId) {
boardCrdt.disconnect()
boardCrdt = undefined
}
})

function getBoardCrdt(boardId: Id): BoardCRDT {
let boardCrdt = boards.get(boardId)
if (!boardCrdt) {
if (boardId != currentBoardId.get()) {
throw Error(`Requested CRDT for board ${boardId} but current board is ${currentBoardId.get()}`)
}

if (!boardCrdt || boardCrdt.boardId !== boardId) {
boardCrdt = BoardCRDT(boardId, online, localBoardItemEvents, getSocketRoot, WebSocketPolyfill)
boards.set(boardId, boardCrdt)
}
return boardCrdt
}

function augmentItems(boardId: Id, items: Item[]): Item[] {
const boardCrdt = boards.get(boardId)
if (!boardCrdt) {
if (!boardCrdt || boardCrdt.boardId !== boardId) {
return items
}
return boardCrdt.augmentItems(items)
}

function cloneBoard(board: Board): Board {
const boardCrdt = boards.get(board.id)
const newId = uuid.v4()
if (!boardCrdt) {
if (!boardCrdt || boardCrdt.boardId !== board.id) {
return {
...board,
id: newId,
Expand All @@ -115,7 +137,9 @@ export function CRDTStore(
id: newId,
}

importItemsIntoCRDT(getBoardCrdt(newId).doc, Object.values(newBoard.items))
const temporaryBoardCrdt = BoardCRDT(newId, online, localBoardItemEvents, getSocketRoot, WebSocketPolyfill)
importItemsIntoCRDT(temporaryBoardCrdt.doc, Object.values(newBoard.items))
temporaryBoardCrdt.disconnect()
return newBoard
}

Expand Down
1 change: 1 addition & 0 deletions perf-tester/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function createTester(nickname: string, boardId: string) {
}

const crdtStore = CRDTStore(
L.constant(boardId),
connection.connected,
localEvents.pipe(L.filter(isPersistableBoardItemEvent)).applyScope(L.globalScope),
() => WS_ROOT,
Expand Down

0 comments on commit 081d8ff

Please sign in to comment.