Skip to content

Commit

Permalink
Create CRDT texts in perftester
Browse files Browse the repository at this point in the history
  • Loading branch information
raimohanska committed Mar 4, 2024
1 parent 99ee76f commit d17483f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 21 deletions.
3 changes: 2 additions & 1 deletion frontend/src/store/board-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { UserSessionState } from "./user-session-store"
import { LocalStorageBoard } from "./board-local-store"
import { sleep } from "../../../common/src/sleep"
import { mkBootStrapEvent } from "../../../common/src/migration"
import * as WebSocket from "ws"

const otherUserEventAttributes = { user: { userType: "unidentified", nickname: "joe" }, timestamp: "0" } as const
const localUser = { userType: "unidentified", nickname: "" } as const
Expand Down Expand Up @@ -303,7 +304,7 @@ async function initBoardStore({
storeBoardState: async (newState: LocalStorageBoard) => {},
}

const store = BoardStore(boardId, connection, sessionInfo, localStore)
const store = BoardStore(boardId, connection, sessionInfo, localStore, WebSocket as any)

expect(store.state.get().board).toEqual(undefined)
expect(store.state.get().queue).toEqual([])
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/store/board-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ import {
newISOTimeStamp,
} from "../../../common/src/domain"
import { BoardLocalStore, LocalStorageBoard } from "./board-local-store"
import { ServerConnection } from "./server-connection"
import { ServerConnection, getWebSocketRootUrl } from "./server-connection"
import { UserSessionState, isLoginInProgress } from "./user-session-store"
import { CRDTStore } from "./crdt-store"
import { CRDTStore, WebSocketPolyfill } from "./crdt-store"
import { serve } from "esbuild"
export type Dispatch = (e: UIEvent) => void
export type BoardStore = ReturnType<typeof BoardStore>
Expand Down Expand Up @@ -71,6 +71,7 @@ export function BoardStore(
connection: ServerConnection,
sessionInfo: L.Property<UserSessionState>,
localStore: BoardLocalStore,
WebSocketPolyfill: WebSocketPolyfill = WebSocket,
) {
type BoardStoreEvent =
| BoardHistoryEntry
Expand Down Expand Up @@ -554,6 +555,8 @@ export function BoardStore(
const crdtStore = CRDTStore(
L.view(state, (s) => s.status === "online"),
localBoardItemEvents,
getWebSocketRootUrl,
WebSocketPolyfill,
)

return {
Expand Down
34 changes: 27 additions & 7 deletions frontend/src/store/crdt-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ import { Board, Id, Item, PersistableBoardItemEvent, QuillDelta, isTextItem } fr
import { getWebSocketRootUrl } from "./server-connection"

type BoardCRDT = ReturnType<typeof BoardCRDT>
export type WebSocketPolyfill =
| {
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket
prototype: WebSocket
readonly CLOSED: number
readonly CLOSING: number
readonly CONNECTING: number
readonly OPEN: number
}
| undefined

function BoardCRDT(
boardId: Id,
online: L.Property<boolean>,
localBoardItemEvents: L.EventStream<PersistableBoardItemEvent>,
getSocketRoot: () => string,
WebSocketPolyfill: WebSocketPolyfill,
) {
const doc = new Y.Doc()

Expand Down Expand Up @@ -55,14 +67,17 @@ function BoardCRDT(
}
}

const persistence = new IndexeddbPersistence(`b/${boardId}`, doc)
if (typeof indexedDB != "undefined") {
const persistence = new IndexeddbPersistence(`b/${boardId}`, doc)

persistence.on("synced", () => {
console.log("CRDT data from indexedDB is loaded")
})
persistence.on("synced", () => {
console.log("CRDT data from indexedDB is loaded")
})
}

const provider = new WebsocketProvider(`${getWebSocketRootUrl()}/socket/yjs`, `board/${boardId}`, doc, {
const provider = new WebsocketProvider(`${getSocketRoot()}/socket/yjs`, `board/${boardId}`, doc, {
connect: online.get(),
WebSocketPolyfill,
})

online.onChange((c) => (c ? provider.connect() : provider.disconnect()))
Expand All @@ -82,12 +97,17 @@ function BoardCRDT(

export type CRDTStore = ReturnType<typeof CRDTStore>

export function CRDTStore(online: L.Property<boolean>, localBoardItemEvents: L.EventStream<PersistableBoardItemEvent>) {
export function CRDTStore(
online: L.Property<boolean>,
localBoardItemEvents: L.EventStream<PersistableBoardItemEvent>,
getSocketRoot: () => string = getWebSocketRootUrl,
WebSocketPolyfill: WebSocketPolyfill = WebSocket,
) {
const boards = new Map<Id, BoardCRDT>()
function getBoardCrdt(boardId: Id): BoardCRDT {
let boardCrdt = boards.get(boardId)
if (!boardCrdt) {
boardCrdt = BoardCRDT(boardId, online, localBoardItemEvents)
boardCrdt = BoardCRDT(boardId, online, localBoardItemEvents, getSocketRoot, WebSocketPolyfill)
boards.set(boardId, boardCrdt)
}
return boardCrdt
Expand Down
41 changes: 30 additions & 11 deletions perf-tester/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { sleep } from "../../common/src/sleep"
import dotenv from "dotenv"
dotenv.config({ path: "../backend/.env" })

import _ from "lodash"
import * as L from "lonna"
import WebSocket from "ws"
import { NOTE_COLORS } from "../../common/src/colors"
import {
CrdtEnabled,
Point,
UIEvent,
defaultBoardSize,
isNote,
isPersistableBoardItemEvent,
isText,
UIEvent,
newNote,
newText,
Point,
EventWrapper,
} from "../../common/src/domain"
import { GenericServerConnection } from "../../frontend/src/store/server-connection"
import { CRDTStore } from "../../frontend/src/store/crdt-store"
import WebSocket from "ws"
import _ from "lodash"
import * as L from "lonna"
import { NOTE_COLORS } from "../../common/src/colors"
import { GenericServerConnection } from "../../frontend/src/store/server-connection"

// hack, sue me
// @ts-ignore
Expand All @@ -32,16 +33,34 @@ function createTester(nickname: string, boardId: string) {
const center = { x: width / 2 - 30 + Math.random() * 60, y: height / 2 - 20 + Math.random() * 40 }
const radius = 10 + Math.random() * 10
const increment = Math.random() * 4 - 2
const WS_ADDRESS = `${DOMAIN ? "wss" : "ws"}://${DOMAIN ?? "localhost:1337"}/socket/board/${boardId}`
const WS_ROOT = `${DOMAIN ? "wss" : "ws"}://${DOMAIN ?? "localhost:1337"}`
const WS_ADDRESS = `${WS_ROOT}/socket/board/${boardId}`

let connection = GenericServerConnection(WS_ADDRESS, L.constant(false), (s) => new WebSocket(s) as any)
let sessionId = ""
connection.bufferedServerEvents.forEach((event) => {
if (event.action === "board.join.ack") {
console.log("Got session id", sessionId)
sessionId = event.sessionId
}
})
const localEvents = L.bus<UIEvent>()
localEvents.forEach(connection.send)

class MyWebSocket extends WebSocket {
constructor(url: string | URL, protocols?: string | string[] | undefined) {
console.log("Creating websocket", url, protocols)
super(url as any, protocols, { headers: { Cookie: `sessionId=${sessionId}` } })
}
}

const crdtStore = CRDTStore(
connection.connected,
localEvents.pipe(L.filter(isPersistableBoardItemEvent)).applyScope(L.globalScope),
() => WS_ROOT,
MyWebSocket as any,
)
crdtStore.getBoardCrdt(boardId)

connection.connected
.pipe(
Expand Down Expand Up @@ -74,7 +93,7 @@ function createTester(nickname: string, boardId: string) {
})
}
if (Math.random() < textsPerInterval) {
const text = newText(CrdtEnabled, "TEXT " + counter, position.x, position.y)
const text = newText(CrdtEnabled, "TEXT " + counter, position.x, position.y, 5, 5)
localEvents.push({
action: "item.add",
boardId,
Expand Down

0 comments on commit d17483f

Please sign in to comment.