From 97b51a915fc1753192774d3cea6f0453fec3e02b Mon Sep 17 00:00:00 2001 From: Nick Kosarev Date: Mon, 2 Dec 2024 17:30:44 +0200 Subject: [PATCH] chore: ws server rework (#279) --- apps/website/server/api/websocket.ts | 58 ++++++++++++----------- apps/website/server/core/rooms/addon.ts | 14 ++++++ apps/website/server/core/rooms/base.ts | 42 +++++++++++++++++ apps/website/server/utils/room.ts | 61 ------------------------- apps/website/types/room.ts | 11 +++++ 5 files changed, 98 insertions(+), 88 deletions(-) create mode 100644 apps/website/server/core/rooms/addon.ts create mode 100644 apps/website/server/core/rooms/base.ts delete mode 100644 apps/website/server/utils/room.ts create mode 100644 apps/website/types/room.ts diff --git a/apps/website/server/api/websocket.ts b/apps/website/server/api/websocket.ts index 981ceea1..13e6cd59 100644 --- a/apps/website/server/api/websocket.ts +++ b/apps/website/server/api/websocket.ts @@ -1,6 +1,7 @@ import type { WebSocketEvents } from '@chat-game/types' +import type { Room } from '~~/types/room' import { createId } from '@paralleldrive/cuid2' -import { Room } from '../utils/room' +import { AddonRoom } from '../core/rooms/addon' const logger = useLogger('ws') export const activeRooms: Room[] = [] @@ -10,7 +11,9 @@ export function sendMessage(message: WebSocketEvents, token: string): void { for (const room of rooms) { const preparedMessage = JSON.stringify({ id: createId(), ...message }) - room.server.send(preparedMessage) + if (room.server.peer?.id) { + room.server.peer.publish(room.id, preparedMessage) + } } } @@ -37,30 +40,30 @@ export default defineWebSocketHandler({ const token = parsed.data.token // Create if not exist if (!activeRooms.find((room) => room.token === token)) { - activeRooms.push(new Room({ id, token, type: 'ADDON' })) + activeRooms.push(new AddonRoom({ id, token })) } - const activeRoom = activeRooms.find((room) => room.token === token) as Room + const activeRoom = activeRooms.find((room) => room.token === token) as AddonRoom peer.subscribe(activeRoom.id) - logger.log(`peer subscribed to room id ${activeRoom.id}`, peer.id) + logger.log(`Peer ${peer.id} subscribed to AddonRoom ${activeRoom.id}`) } - if (client === 'GAME') { - const token = parsed.data.token - // Create if not exist - if (!activeRooms.find((room) => room.token === token)) { - activeRooms.push(new Room({ id, token, type: 'GAME' })) - } + // if (client === 'GAME') { + // const token = parsed.data.token + // // Create if not exist + // if (!activeRooms.find((room) => room.token === token)) { + // activeRooms.push(new Room({ id, token, type: 'GAME' })) + // } - const activeRoom = activeRooms.find((room) => room.token === token) as Room - if (!activeRoom.peers.includes(peer.id)) { - activeRoom.peers.push(peer.id) - } + // const activeRoom = activeRooms.find((room) => room.token === token) as Room + // if (!activeRoom.peers.includes(peer.id)) { + // activeRoom.peers.push(peer.id) + // } - peer.subscribe(activeRoom.id) - logger.log(`peer subscribed to room id ${activeRoom.id}`, peer.id) - } + // peer.subscribe(activeRoom.id) + // logger.log(`peer subscribed to room id ${activeRoom.id}`, peer.id) + // } if (client === 'SERVER') { const activeRoom = activeRooms.find((room) => room.id === id) @@ -68,21 +71,22 @@ export default defineWebSocketHandler({ return } + activeRoom.server.peer = peer peer.subscribe(activeRoom.id) - logger.log(`server subscribed to room id ${activeRoom.id}`, peer.id) + logger.log(`Server subscribed to Room ${activeRoom.id}`, peer.id) } } if (parsed.type === 'TEST') { peer.publish(parsed.data.id, JSON.stringify({ id: createId(), type: 'TEST' })) } - if (parsed.type === 'NEW_TREE') { - const room = activeRooms.find((room) => room.peers.find((id) => id === peer.id)) - if (!room) { - return - } - peer.publish(room.id, JSON.stringify({ id: createId(), type: 'NEW_TREE', data: { id: parsed.data.id, x: parsed.data.x } })) - peer.send(JSON.stringify({ id: createId(), type: 'NEW_TREE', data: { id: parsed.data.id, x: parsed.data.x } })) - } + // if (parsed.type === 'NEW_TREE') { + // const room = activeRooms.find((room) => room.peers.find((id) => id === peer.id)) + // if (!room) { + // return + // } + // peer.publish(room.id, JSON.stringify({ id: createId(), type: 'NEW_TREE', data: { id: parsed.data.id, x: parsed.data.x } })) + // peer.send(JSON.stringify({ id: createId(), type: 'NEW_TREE', data: { id: parsed.data.id, x: parsed.data.x } })) + // } } }, diff --git a/apps/website/server/core/rooms/addon.ts b/apps/website/server/core/rooms/addon.ts new file mode 100644 index 00000000..a8de91ac --- /dev/null +++ b/apps/website/server/core/rooms/addon.ts @@ -0,0 +1,14 @@ +import { BaseRoom } from './base' + +interface AddonRoomOptions { + id: string + token: string +} + +export class AddonRoom extends BaseRoom { + peers: string[] = [] + + constructor({ id, token }: AddonRoomOptions) { + super({ id, token, type: 'ADDON' }) + } +} diff --git a/apps/website/server/core/rooms/base.ts b/apps/website/server/core/rooms/base.ts new file mode 100644 index 00000000..56bfe54a --- /dev/null +++ b/apps/website/server/core/rooms/base.ts @@ -0,0 +1,42 @@ +import type { Peer } from 'crossws' +import type { Room } from '~~/types/room' +import { createId } from '@paralleldrive/cuid2' + +interface BaseRoomOptions { + id: string + token: string + type: Room['type'] +} + +export class BaseRoom implements Room { + id: string + token: string + type: Room['type'] + server: { ws: WebSocket, peer: Peer | null } + + constructor({ id, token, type }: BaseRoomOptions) { + this.id = id + this.token = token + this.type = type + + const { public: publicEnv } = useRuntimeConfig() + + this.server = { + ws: new WebSocket(publicEnv.websocketUrl), + peer: null, + } + + this.server.ws.onopen = () => { + const prepearedMessage = JSON.stringify({ + id: createId(), + type: 'CONNECT', + data: { + client: 'SERVER', + id: this.id, + token: this.token, + }, + }) + this.server.ws.send(prepearedMessage) + } + } +} diff --git a/apps/website/server/utils/room.ts b/apps/website/server/utils/room.ts deleted file mode 100644 index dae38698..00000000 --- a/apps/website/server/utils/room.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { createId } from '@paralleldrive/cuid2' - -interface RoomOptions { - id: string - token: string - type: 'ADDON' | 'GAME' -} - -export class Room { - id: string - token: string - type: 'ADDON' | 'GAME' - peers: string[] = [] - server!: WebSocket - - constructor({ id, token, type }: RoomOptions) { - this.id = id - this.token = token - this.type = type - - const { public: publicEnv } = useRuntimeConfig() - - if (type === 'ADDON') { - this.server = new WebSocket(publicEnv.websocketUrl) - - this.server.onopen = () => { - const prepearedMessage = JSON.stringify({ - id: createId(), - type: 'CONNECT', - data: { - client: 'SERVER', - id: this.id, - token: this.token, - }, - }) - this.server.send(prepearedMessage) - } - } - - if (type === 'GAME') { - this.server = new WebSocket(publicEnv.websocketUrl) - - this.server.onopen = () => { - const prepearedMessage = JSON.stringify({ - id: createId(), - type: 'CONNECT', - data: { - client: 'SERVER', - id: this.id, - token: this.token, - }, - }) - this.server.send(prepearedMessage) - } - - setInterval(() => { - this.server.send(JSON.stringify({ id: 1, type: 'TEST', data: { id: this.id } })) - }, 10000) - } - } -} diff --git a/apps/website/types/room.ts b/apps/website/types/room.ts new file mode 100644 index 00000000..965da3ab --- /dev/null +++ b/apps/website/types/room.ts @@ -0,0 +1,11 @@ +import type { Peer } from 'crossws' + +export interface Room { + id: string + type: 'ADDON' | 'GAME' + token: string + server: { + ws: WebSocket + peer: Peer | null + } +}