@colyseus/core 0.14.35 → 0.14.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/MatchMaker.js
CHANGED
|
@@ -136,7 +136,7 @@ async function remoteRoomCall(roomId, method, args, rejectionTimeout = Utils.REM
|
|
|
136
136
|
else {
|
|
137
137
|
return (!args && typeof (room[method]) !== 'function')
|
|
138
138
|
? room[method]
|
|
139
|
-
: (await room[method].apply(room, args));
|
|
139
|
+
: (await room[method].apply(room, args && args.map((arg) => JSON.parse(JSON.stringify(arg)))));
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
function defineRoomType(name, klass, defaultOptions) {
|
package/build/MatchMaker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchMaker.js","sources":["../src/MatchMaker.ts"],"sourcesContent":["import { ErrorCode } from './Protocol';\n\nimport { requestFromIPC, subscribeIPC } from './IPC';\nimport { generateId, merge, REMOTE_ROOM_SHORT_TIMEOUT, retry } from './Utils';\n\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Room, RoomInternalState } from './Room';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { Presence } from './presence/Presence';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport { SeatReservationError } from './errors/SeatReservationError';\nimport { ServerError } from './errors/ServerError';\n\nimport { IRoomListingData, MatchMakerDriver, RoomListingData, LocalDriver } from './matchmaker/driver';\nimport * as controller from './matchmaker/controller';\n\nimport { Client } from './Transport';\nimport { Type } from './types';\n\nexport { MatchMakerDriver, controller };\n\nexport type ClientOptions = any;\n\nexport interface SeatReservation {\n sessionId: string;\n room: RoomListingData;\n}\n\nconst handlers: {[id: string]: RegisteredHandler} = {};\nconst rooms: {[roomId: string]: Room} = {};\n\nexport let processId: string;\nexport let presence: Presence;\nexport let driver: MatchMakerDriver;\n\nlet isGracefullyShuttingDown: boolean;\n\nexport function setup(_presence?: Presence, _driver?: MatchMakerDriver, _processId?: string) {\n presence = _presence || new LocalPresence();\n driver = _driver || new LocalDriver();\n processId = _processId;\n isGracefullyShuttingDown = false;\n\n /**\n * Subscribe to remote `handleCreateRoom` calls.\n */\n subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {\n return handleCreateRoom.apply(undefined, args);\n });\n\n presence.hset(getRoomCountKey(), processId, '0');\n}\n\n/**\n * Join or create into a room and return seat reservation\n */\nexport async function joinOrCreate(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n let room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n room = await createRoom(roomName, clientOptions);\n }\n\n return await reserveSeatFor(room, clientOptions);\n }, 5, [SeatReservationError]);\n}\n\n/**\n * Create a room and return seat reservation\n */\nexport async function create(roomName: string, clientOptions: ClientOptions = {}) {\n const room = await createRoom(roomName, clientOptions);\n return reserveSeatFor(room, clientOptions);\n}\n\n/**\n * Join a room and return seat reservation\n */\nexport async function join(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n const room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n throw new ServerError(ErrorCode.MATCHMAKE_INVALID_CRITERIA, `no rooms found with provided criteria`);\n }\n\n return reserveSeatFor(room, clientOptions);\n });\n}\n\n/**\n * Join a room by id and return seat reservation\n */\nexport async function joinById(roomId: string, clientOptions: ClientOptions = {}) {\n const room = await driver.findOne({ roomId });\n\n if (room) {\n const rejoinSessionId = clientOptions.sessionId;\n\n if (rejoinSessionId) {\n // handle re-connection!\n const hasReservedSeat = await remoteRoomCall(room.roomId, 'hasReservedSeat', [rejoinSessionId]);\n\n if (hasReservedSeat) {\n return { room, sessionId: rejoinSessionId };\n\n } else {\n throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, `session expired: ${rejoinSessionId}`);\n\n }\n\n } else if (!room.locked) {\n return reserveSeatFor(room, clientOptions);\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" is locked`);\n\n }\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" not found`);\n }\n\n}\n\n/**\n * Perform a query for all cached rooms\n */\nexport async function query(conditions: Partial<IRoomListingData> = {}) {\n return await driver.find(conditions);\n}\n\n/**\n * Find for a public and unlocked room available\n */\nexport async function findOneRoomAvailable(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n return await awaitRoomAvailable(roomName, async () => {\n const handler = handlers[roomName];\n if (!handler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const roomQuery = driver.findOne({\n locked: false,\n name: roomName,\n private: false,\n ...handler.getFilterOptions(clientOptions),\n });\n\n if (handler.sortOptions) {\n roomQuery.sort(handler.sortOptions);\n }\n\n return await roomQuery;\n });\n}\n\n/**\n * Call a method or return a property on a remote room.\n */\nexport async function remoteRoomCall<R= any>(\n roomId: string,\n method: string,\n args?: any[],\n rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,\n): Promise<R> {\n const room = rooms[roomId];\n\n if (!room) {\n try {\n return await requestFromIPC<R>(presence, getRoomChannel(roomId), method, args);\n\n } catch (e) {\n const request = `${method}${args && ' with args ' + JSON.stringify(args) || ''}`;\n throw new ServerError(\n ErrorCode.MATCHMAKE_UNHANDLED,\n `remote room (${roomId}) timed out, requesting \"${request}\". (${rejectionTimeout}ms exceeded)`,\n );\n }\n\n } else {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : (await room[method].apply(room, args));\n }\n}\n\nexport function defineRoomType<T extends Type<Room>>(\n name: string,\n klass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n) {\n const registeredHandler = new RegisteredHandler(klass, defaultOptions);\n\n handlers[name] = registeredHandler;\n\n cleanupStaleRooms(name);\n\n return registeredHandler;\n}\n\nexport function removeRoomType(name: string) {\n delete handlers[name];\n cleanupStaleRooms(name);\n}\n\nexport function hasHandler(name: string) {\n return handlers[ name ] !== undefined;\n}\n\n/**\n * Create a room\n */\nexport async function createRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const roomsSpawnedByProcessId = await presence.hgetall(getRoomCountKey());\n\n const processIdWithFewerRooms = (\n Object.keys(roomsSpawnedByProcessId).sort((p1, p2) => {\n return (Number(roomsSpawnedByProcessId[p1]) > Number(roomsSpawnedByProcessId[p2]))\n ? 1\n : -1;\n })[0]\n ) || processId;\n\n if (processIdWithFewerRooms === processId) {\n // create the room on this process!\n return await handleCreateRoom(roomName, clientOptions);\n\n } else {\n // ask other process to create the room!\n let room: RoomListingData;\n\n try {\n room = await requestFromIPC<RoomListingData>(\n presence,\n getProcessChannel(processIdWithFewerRooms),\n undefined,\n [roomName, clientOptions],\n REMOTE_ROOM_SHORT_TIMEOUT,\n );\n\n } catch (e) {\n // if other process failed to respond, create the room on this process\n debugAndPrintError(e);\n room = await handleCreateRoom(roomName, clientOptions);\n }\n\n return room;\n }\n}\n\nasync function handleCreateRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const registeredHandler = handlers[roomName];\n\n if (!registeredHandler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const room = new registeredHandler.klass();\n\n // set room public attributes\n room.roomId = generateId();\n room.roomName = roomName;\n room.presence = presence;\n\n // create a RoomCache reference.\n room.listing = driver.createInstance({\n name: roomName,\n processId,\n ...registeredHandler.getFilterOptions(clientOptions),\n });\n\n if (room.onCreate) {\n try {\n await room.onCreate(merge({}, clientOptions, registeredHandler.options));\n\n // increment amount of rooms this process is handling\n presence.hincrby(getRoomCountKey(), processId, 1);\n\n } catch (e) {\n debugAndPrintError(e);\n throw new ServerError(\n e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n e.message,\n );\n }\n }\n\n room.internalState = RoomInternalState.CREATED;\n\n room.listing.roomId = room.roomId;\n room.listing.maxClients = room.maxClients;\n\n // imediatelly ask client to join the room\n debugMatchMaking('spawning \\'%s\\', roomId: %s, processId: %s', roomName, room.roomId, processId);\n\n room._events.on('lock', lockRoom.bind(this, room));\n room._events.on('unlock', unlockRoom.bind(this, room));\n room._events.on('join', onClientJoinRoom.bind(this, room));\n room._events.on('leave', onClientLeaveRoom.bind(this, room));\n room._events.once('dispose', disposeRoom.bind(this, roomName, room));\n room._events.once('disconnect', () => room._events.removeAllListeners());\n\n // room always start unlocked\n await createRoomReferences(room, true);\n await room.listing.save();\n\n registeredHandler.emit('create', room);\n\n return room.listing;\n}\n\nexport function getRoomById(roomId: string) {\n return rooms[roomId];\n}\n\n/**\n * Disconnects every client on every room in the current process.\n */\nexport function disconnectAll() {\n const promises: Array<Promise<any>> = [];\n\n for (const roomId in rooms) {\n if (!rooms.hasOwnProperty(roomId)) { continue; }\n promises.push(rooms[roomId].disconnect());\n }\n\n return promises;\n}\n\nexport function gracefullyShutdown(): Promise<any> {\n if (isGracefullyShuttingDown) {\n return Promise.reject('already_shutting_down');\n }\n\n isGracefullyShuttingDown = true;\n\n debugMatchMaking(`${processId} is shutting down!`);\n\n // remove processId from room count key\n presence.hdel(getRoomCountKey(), processId);\n\n // unsubscribe from process id channel\n presence.unsubscribe(getProcessChannel());\n\n return Promise.all(disconnectAll());\n}\n\n/**\n * Reserve a seat for a client in a room\n */\nexport async function reserveSeatFor(room: RoomListingData, options: any) {\n const sessionId: string = generateId();\n\n debugMatchMaking(\n 'reserving seat. sessionId: \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'',\n sessionId, room.roomId, processId,\n );\n\n let successfulSeatReservation: boolean;\n\n try {\n successfulSeatReservation = await remoteRoomCall(room.roomId, '_reserveSeat', [sessionId, options]);\n\n } catch (e) {\n debugMatchMaking(e);\n successfulSeatReservation = false;\n }\n\n if (!successfulSeatReservation) {\n throw new SeatReservationError(`${room.roomId} is already full.`);\n }\n\n return { room, sessionId };\n}\n\nasync function cleanupStaleRooms(roomName: string) {\n //\n // clean-up possibly stale room ids\n // (ungraceful shutdowns using Redis can result on stale room ids still on memory.)\n //\n const cachedRooms = await driver.find({ name: roomName }, { _id: 1 });\n\n // remove connecting counts\n await presence.del(getHandlerConcurrencyKey(roomName));\n\n await Promise.all(cachedRooms.map(async (room) => {\n try {\n // use hardcoded short timeout for cleaning up stale rooms.\n await remoteRoomCall(room.roomId, 'roomId');\n\n } catch (e) {\n debugMatchMaking(`cleaning up stale room '${roomName}', roomId: ${room.roomId}`);\n room.remove();\n }\n }));\n}\n\nasync function createRoomReferences(room: Room, init: boolean = false): Promise<boolean> {\n rooms[room.roomId] = room;\n\n if (init) {\n await subscribeIPC(\n presence,\n processId,\n getRoomChannel(room.roomId),\n (method, args) => {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : room[method].apply(room, args);\n },\n );\n }\n\n return true;\n}\n\nasync function awaitRoomAvailable(roomToJoin: string, callback: Function): Promise<RoomListingData> {\n return new Promise(async (resolve, reject) => {\n const concurrencyKey = getHandlerConcurrencyKey(roomToJoin);\n const concurrency = await presence.incr(concurrencyKey) - 1;\n\n // avoid having too long timeout if 10+ clients ask to join at the same time\n const concurrencyTimeout = Math.min(concurrency * 100, REMOTE_ROOM_SHORT_TIMEOUT);\n\n if (concurrency > 0) {\n debugMatchMaking(\n 'receiving %d concurrent requests for joining \\'%s\\' (waiting %d ms)',\n concurrency, roomToJoin, concurrencyTimeout,\n );\n }\n\n setTimeout(async () => {\n try {\n const result = await callback();\n resolve(result);\n\n } catch (e) {\n reject(e);\n\n } finally {\n await presence.decr(concurrencyKey);\n }\n }, concurrencyTimeout);\n });\n}\n\nfunction onClientJoinRoom(room: Room, client: Client) {\n handlers[room.roomName].emit('join', room, client);\n}\n\nfunction onClientLeaveRoom(room: Room, client: Client, willDispose: boolean) {\n handlers[room.roomName].emit('leave', room, client, willDispose);\n}\n\nfunction lockRoom(room: Room): void {\n // emit public event on registered handler\n handlers[room.roomName].emit('lock', room);\n}\n\nasync function unlockRoom(room: Room) {\n if (await createRoomReferences(room)) {\n // emit public event on registered handler\n handlers[room.roomName].emit('unlock', room);\n }\n}\n\nasync function disposeRoom(roomName: string, room: Room) {\n debugMatchMaking('disposing \\'%s\\' (%s) on processId \\'%s\\'', roomName, room.roomId, processId);\n\n // decrease amount of rooms this process is handling\n if (!isGracefullyShuttingDown) {\n presence.hincrby(getRoomCountKey(), processId, -1);\n }\n\n // remove from room listing (already removed if `disconnect()` has been called)\n if (room.internalState !== RoomInternalState.DISCONNECTING) {\n await room.listing.remove();\n }\n\n // emit disposal on registered session handler\n handlers[roomName].emit('dispose', room);\n\n // remove concurrency key\n presence.del(getHandlerConcurrencyKey(roomName));\n\n // unsubscribe from remote connections\n presence.unsubscribe(getRoomChannel(room.roomId));\n\n // remove actual room reference\n delete rooms[room.roomId];\n}\n\n//\n// Presence keys\n//\n\nfunction getRoomChannel(roomId: string) {\n return `$${roomId}`;\n}\n\nfunction getHandlerConcurrencyKey(name: string) {\n return `c:${name}`;\n}\n\nfunction getProcessChannel(id: string = processId) {\n return `p:${id}`;\n}\n\nfunction getRoomCountKey() {\n return 'roomcount';\n}\n"],"names":["processId","presence","driver","LocalPresence","LocalDriver","subscribeIPC","retry","SeatReservationError","ServerError","ErrorCode","REMOTE_ROOM_SHORT_TIMEOUT","requestFromIPC","RegisteredHandler","debugAndPrintError","generateId","merge","RoomInternalState","debugMatchMaking"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MatchMaker.js","sources":["../src/MatchMaker.ts"],"sourcesContent":["import { ErrorCode } from './Protocol';\n\nimport { requestFromIPC, subscribeIPC } from './IPC';\nimport { generateId, merge, REMOTE_ROOM_SHORT_TIMEOUT, retry } from './Utils';\n\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Room, RoomInternalState } from './Room';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { Presence } from './presence/Presence';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport { SeatReservationError } from './errors/SeatReservationError';\nimport { ServerError } from './errors/ServerError';\n\nimport { IRoomListingData, MatchMakerDriver, RoomListingData, LocalDriver } from './matchmaker/driver';\nimport * as controller from './matchmaker/controller';\n\nimport { Client } from './Transport';\nimport { Type } from './types';\n\nexport { MatchMakerDriver, controller };\n\nexport type ClientOptions = any;\n\nexport interface SeatReservation {\n sessionId: string;\n room: RoomListingData;\n}\n\nconst handlers: {[id: string]: RegisteredHandler} = {};\nconst rooms: {[roomId: string]: Room} = {};\n\nexport let processId: string;\nexport let presence: Presence;\nexport let driver: MatchMakerDriver;\n\nlet isGracefullyShuttingDown: boolean;\n\nexport function setup(_presence?: Presence, _driver?: MatchMakerDriver, _processId?: string) {\n presence = _presence || new LocalPresence();\n driver = _driver || new LocalDriver();\n processId = _processId;\n isGracefullyShuttingDown = false;\n\n /**\n * Subscribe to remote `handleCreateRoom` calls.\n */\n subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {\n return handleCreateRoom.apply(undefined, args);\n });\n\n presence.hset(getRoomCountKey(), processId, '0');\n}\n\n/**\n * Join or create into a room and return seat reservation\n */\nexport async function joinOrCreate(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n let room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n room = await createRoom(roomName, clientOptions);\n }\n\n return await reserveSeatFor(room, clientOptions);\n }, 5, [SeatReservationError]);\n}\n\n/**\n * Create a room and return seat reservation\n */\nexport async function create(roomName: string, clientOptions: ClientOptions = {}) {\n const room = await createRoom(roomName, clientOptions);\n return reserveSeatFor(room, clientOptions);\n}\n\n/**\n * Join a room and return seat reservation\n */\nexport async function join(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n const room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n throw new ServerError(ErrorCode.MATCHMAKE_INVALID_CRITERIA, `no rooms found with provided criteria`);\n }\n\n return reserveSeatFor(room, clientOptions);\n });\n}\n\n/**\n * Join a room by id and return seat reservation\n */\nexport async function joinById(roomId: string, clientOptions: ClientOptions = {}) {\n const room = await driver.findOne({ roomId });\n\n if (room) {\n const rejoinSessionId = clientOptions.sessionId;\n\n if (rejoinSessionId) {\n // handle re-connection!\n const hasReservedSeat = await remoteRoomCall(room.roomId, 'hasReservedSeat', [rejoinSessionId]);\n\n if (hasReservedSeat) {\n return { room, sessionId: rejoinSessionId };\n\n } else {\n throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, `session expired: ${rejoinSessionId}`);\n\n }\n\n } else if (!room.locked) {\n return reserveSeatFor(room, clientOptions);\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" is locked`);\n\n }\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" not found`);\n }\n\n}\n\n/**\n * Perform a query for all cached rooms\n */\nexport async function query(conditions: Partial<IRoomListingData> = {}) {\n return await driver.find(conditions);\n}\n\n/**\n * Find for a public and unlocked room available\n */\nexport async function findOneRoomAvailable(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n return await awaitRoomAvailable(roomName, async () => {\n const handler = handlers[roomName];\n if (!handler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const roomQuery = driver.findOne({\n locked: false,\n name: roomName,\n private: false,\n ...handler.getFilterOptions(clientOptions),\n });\n\n if (handler.sortOptions) {\n roomQuery.sort(handler.sortOptions);\n }\n\n return await roomQuery;\n });\n}\n\n/**\n * Call a method or return a property on a remote room.\n */\nexport async function remoteRoomCall<R= any>(\n roomId: string,\n method: string,\n args?: any[],\n rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,\n): Promise<R> {\n const room = rooms[roomId];\n\n if (!room) {\n try {\n return await requestFromIPC<R>(presence, getRoomChannel(roomId), method, args);\n\n } catch (e) {\n const request = `${method}${args && ' with args ' + JSON.stringify(args) || ''}`;\n throw new ServerError(\n ErrorCode.MATCHMAKE_UNHANDLED,\n `remote room (${roomId}) timed out, requesting \"${request}\". (${rejectionTimeout}ms exceeded)`,\n );\n }\n\n } else {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : (await room[method].apply(room, args && args.map((arg) => JSON.parse(JSON.stringify(arg)))));\n }\n}\n\nexport function defineRoomType<T extends Type<Room>>(\n name: string,\n klass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n) {\n const registeredHandler = new RegisteredHandler(klass, defaultOptions);\n\n handlers[name] = registeredHandler;\n\n cleanupStaleRooms(name);\n\n return registeredHandler;\n}\n\nexport function removeRoomType(name: string) {\n delete handlers[name];\n cleanupStaleRooms(name);\n}\n\nexport function hasHandler(name: string) {\n return handlers[ name ] !== undefined;\n}\n\n/**\n * Create a room\n */\nexport async function createRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const roomsSpawnedByProcessId = await presence.hgetall(getRoomCountKey());\n\n const processIdWithFewerRooms = (\n Object.keys(roomsSpawnedByProcessId).sort((p1, p2) => {\n return (Number(roomsSpawnedByProcessId[p1]) > Number(roomsSpawnedByProcessId[p2]))\n ? 1\n : -1;\n })[0]\n ) || processId;\n\n if (processIdWithFewerRooms === processId) {\n // create the room on this process!\n return await handleCreateRoom(roomName, clientOptions);\n\n } else {\n // ask other process to create the room!\n let room: RoomListingData;\n\n try {\n room = await requestFromIPC<RoomListingData>(\n presence,\n getProcessChannel(processIdWithFewerRooms),\n undefined,\n [roomName, clientOptions],\n REMOTE_ROOM_SHORT_TIMEOUT,\n );\n\n } catch (e) {\n // if other process failed to respond, create the room on this process\n debugAndPrintError(e);\n room = await handleCreateRoom(roomName, clientOptions);\n }\n\n return room;\n }\n}\n\nasync function handleCreateRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const registeredHandler = handlers[roomName];\n\n if (!registeredHandler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const room = new registeredHandler.klass();\n\n // set room public attributes\n room.roomId = generateId();\n room.roomName = roomName;\n room.presence = presence;\n\n // create a RoomCache reference.\n room.listing = driver.createInstance({\n name: roomName,\n processId,\n ...registeredHandler.getFilterOptions(clientOptions),\n });\n\n if (room.onCreate) {\n try {\n await room.onCreate(merge({}, clientOptions, registeredHandler.options));\n\n // increment amount of rooms this process is handling\n presence.hincrby(getRoomCountKey(), processId, 1);\n\n } catch (e) {\n debugAndPrintError(e);\n throw new ServerError(\n e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n e.message,\n );\n }\n }\n\n room.internalState = RoomInternalState.CREATED;\n\n room.listing.roomId = room.roomId;\n room.listing.maxClients = room.maxClients;\n\n // imediatelly ask client to join the room\n debugMatchMaking('spawning \\'%s\\', roomId: %s, processId: %s', roomName, room.roomId, processId);\n\n room._events.on('lock', lockRoom.bind(this, room));\n room._events.on('unlock', unlockRoom.bind(this, room));\n room._events.on('join', onClientJoinRoom.bind(this, room));\n room._events.on('leave', onClientLeaveRoom.bind(this, room));\n room._events.once('dispose', disposeRoom.bind(this, roomName, room));\n room._events.once('disconnect', () => room._events.removeAllListeners());\n\n // room always start unlocked\n await createRoomReferences(room, true);\n await room.listing.save();\n\n registeredHandler.emit('create', room);\n\n return room.listing;\n}\n\nexport function getRoomById(roomId: string) {\n return rooms[roomId];\n}\n\n/**\n * Disconnects every client on every room in the current process.\n */\nexport function disconnectAll() {\n const promises: Array<Promise<any>> = [];\n\n for (const roomId in rooms) {\n if (!rooms.hasOwnProperty(roomId)) { continue; }\n promises.push(rooms[roomId].disconnect());\n }\n\n return promises;\n}\n\nexport function gracefullyShutdown(): Promise<any> {\n if (isGracefullyShuttingDown) {\n return Promise.reject('already_shutting_down');\n }\n\n isGracefullyShuttingDown = true;\n\n debugMatchMaking(`${processId} is shutting down!`);\n\n // remove processId from room count key\n presence.hdel(getRoomCountKey(), processId);\n\n // unsubscribe from process id channel\n presence.unsubscribe(getProcessChannel());\n\n return Promise.all(disconnectAll());\n}\n\n/**\n * Reserve a seat for a client in a room\n */\nexport async function reserveSeatFor(room: RoomListingData, options: any) {\n const sessionId: string = generateId();\n\n debugMatchMaking(\n 'reserving seat. sessionId: \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'',\n sessionId, room.roomId, processId,\n );\n\n let successfulSeatReservation: boolean;\n\n try {\n successfulSeatReservation = await remoteRoomCall(room.roomId, '_reserveSeat', [sessionId, options]);\n\n } catch (e) {\n debugMatchMaking(e);\n successfulSeatReservation = false;\n }\n\n if (!successfulSeatReservation) {\n throw new SeatReservationError(`${room.roomId} is already full.`);\n }\n\n return { room, sessionId };\n}\n\nasync function cleanupStaleRooms(roomName: string) {\n //\n // clean-up possibly stale room ids\n // (ungraceful shutdowns using Redis can result on stale room ids still on memory.)\n //\n const cachedRooms = await driver.find({ name: roomName }, { _id: 1 });\n\n // remove connecting counts\n await presence.del(getHandlerConcurrencyKey(roomName));\n\n await Promise.all(cachedRooms.map(async (room) => {\n try {\n // use hardcoded short timeout for cleaning up stale rooms.\n await remoteRoomCall(room.roomId, 'roomId');\n\n } catch (e) {\n debugMatchMaking(`cleaning up stale room '${roomName}', roomId: ${room.roomId}`);\n room.remove();\n }\n }));\n}\n\nasync function createRoomReferences(room: Room, init: boolean = false): Promise<boolean> {\n rooms[room.roomId] = room;\n\n if (init) {\n await subscribeIPC(\n presence,\n processId,\n getRoomChannel(room.roomId),\n (method, args) => {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : room[method].apply(room, args);\n },\n );\n }\n\n return true;\n}\n\nasync function awaitRoomAvailable(roomToJoin: string, callback: Function): Promise<RoomListingData> {\n return new Promise(async (resolve, reject) => {\n const concurrencyKey = getHandlerConcurrencyKey(roomToJoin);\n const concurrency = await presence.incr(concurrencyKey) - 1;\n\n // avoid having too long timeout if 10+ clients ask to join at the same time\n const concurrencyTimeout = Math.min(concurrency * 100, REMOTE_ROOM_SHORT_TIMEOUT);\n\n if (concurrency > 0) {\n debugMatchMaking(\n 'receiving %d concurrent requests for joining \\'%s\\' (waiting %d ms)',\n concurrency, roomToJoin, concurrencyTimeout,\n );\n }\n\n setTimeout(async () => {\n try {\n const result = await callback();\n resolve(result);\n\n } catch (e) {\n reject(e);\n\n } finally {\n await presence.decr(concurrencyKey);\n }\n }, concurrencyTimeout);\n });\n}\n\nfunction onClientJoinRoom(room: Room, client: Client) {\n handlers[room.roomName].emit('join', room, client);\n}\n\nfunction onClientLeaveRoom(room: Room, client: Client, willDispose: boolean) {\n handlers[room.roomName].emit('leave', room, client, willDispose);\n}\n\nfunction lockRoom(room: Room): void {\n // emit public event on registered handler\n handlers[room.roomName].emit('lock', room);\n}\n\nasync function unlockRoom(room: Room) {\n if (await createRoomReferences(room)) {\n // emit public event on registered handler\n handlers[room.roomName].emit('unlock', room);\n }\n}\n\nasync function disposeRoom(roomName: string, room: Room) {\n debugMatchMaking('disposing \\'%s\\' (%s) on processId \\'%s\\'', roomName, room.roomId, processId);\n\n // decrease amount of rooms this process is handling\n if (!isGracefullyShuttingDown) {\n presence.hincrby(getRoomCountKey(), processId, -1);\n }\n\n // remove from room listing (already removed if `disconnect()` has been called)\n if (room.internalState !== RoomInternalState.DISCONNECTING) {\n await room.listing.remove();\n }\n\n // emit disposal on registered session handler\n handlers[roomName].emit('dispose', room);\n\n // remove concurrency key\n presence.del(getHandlerConcurrencyKey(roomName));\n\n // unsubscribe from remote connections\n presence.unsubscribe(getRoomChannel(room.roomId));\n\n // remove actual room reference\n delete rooms[room.roomId];\n}\n\n//\n// Presence keys\n//\n\nfunction getRoomChannel(roomId: string) {\n return `$${roomId}`;\n}\n\nfunction getHandlerConcurrencyKey(name: string) {\n return `c:${name}`;\n}\n\nfunction getProcessChannel(id: string = processId) {\n return `p:${id}`;\n}\n\nfunction getRoomCountKey() {\n return 'roomcount';\n}\n"],"names":["processId","presence","driver","LocalPresence","LocalDriver","subscribeIPC","retry","SeatReservationError","ServerError","ErrorCode","REMOTE_ROOM_SHORT_TIMEOUT","requestFromIPC","RegisteredHandler","debugAndPrintError","generateId","merge","RoomInternalState","debugMatchMaking"],"mappings":"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"}
|
package/build/MatchMaker.mjs
CHANGED
|
@@ -133,7 +133,7 @@ async function remoteRoomCall(roomId, method, args, rejectionTimeout = REMOTE_RO
|
|
|
133
133
|
else {
|
|
134
134
|
return (!args && typeof (room[method]) !== 'function')
|
|
135
135
|
? room[method]
|
|
136
|
-
: (await room[method].apply(room, args));
|
|
136
|
+
: (await room[method].apply(room, args && args.map((arg) => JSON.parse(JSON.stringify(arg)))));
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
function defineRoomType(name, klass, defaultOptions) {
|
package/build/MatchMaker.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchMaker.mjs","sources":["../src/MatchMaker.ts"],"sourcesContent":["import { ErrorCode } from './Protocol';\n\nimport { requestFromIPC, subscribeIPC } from './IPC';\nimport { generateId, merge, REMOTE_ROOM_SHORT_TIMEOUT, retry } from './Utils';\n\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Room, RoomInternalState } from './Room';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { Presence } from './presence/Presence';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport { SeatReservationError } from './errors/SeatReservationError';\nimport { ServerError } from './errors/ServerError';\n\nimport { IRoomListingData, MatchMakerDriver, RoomListingData, LocalDriver } from './matchmaker/driver';\nimport * as controller from './matchmaker/controller';\n\nimport { Client } from './Transport';\nimport { Type } from './types';\n\nexport { MatchMakerDriver, controller };\n\nexport type ClientOptions = any;\n\nexport interface SeatReservation {\n sessionId: string;\n room: RoomListingData;\n}\n\nconst handlers: {[id: string]: RegisteredHandler} = {};\nconst rooms: {[roomId: string]: Room} = {};\n\nexport let processId: string;\nexport let presence: Presence;\nexport let driver: MatchMakerDriver;\n\nlet isGracefullyShuttingDown: boolean;\n\nexport function setup(_presence?: Presence, _driver?: MatchMakerDriver, _processId?: string) {\n presence = _presence || new LocalPresence();\n driver = _driver || new LocalDriver();\n processId = _processId;\n isGracefullyShuttingDown = false;\n\n /**\n * Subscribe to remote `handleCreateRoom` calls.\n */\n subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {\n return handleCreateRoom.apply(undefined, args);\n });\n\n presence.hset(getRoomCountKey(), processId, '0');\n}\n\n/**\n * Join or create into a room and return seat reservation\n */\nexport async function joinOrCreate(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n let room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n room = await createRoom(roomName, clientOptions);\n }\n\n return await reserveSeatFor(room, clientOptions);\n }, 5, [SeatReservationError]);\n}\n\n/**\n * Create a room and return seat reservation\n */\nexport async function create(roomName: string, clientOptions: ClientOptions = {}) {\n const room = await createRoom(roomName, clientOptions);\n return reserveSeatFor(room, clientOptions);\n}\n\n/**\n * Join a room and return seat reservation\n */\nexport async function join(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n const room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n throw new ServerError(ErrorCode.MATCHMAKE_INVALID_CRITERIA, `no rooms found with provided criteria`);\n }\n\n return reserveSeatFor(room, clientOptions);\n });\n}\n\n/**\n * Join a room by id and return seat reservation\n */\nexport async function joinById(roomId: string, clientOptions: ClientOptions = {}) {\n const room = await driver.findOne({ roomId });\n\n if (room) {\n const rejoinSessionId = clientOptions.sessionId;\n\n if (rejoinSessionId) {\n // handle re-connection!\n const hasReservedSeat = await remoteRoomCall(room.roomId, 'hasReservedSeat', [rejoinSessionId]);\n\n if (hasReservedSeat) {\n return { room, sessionId: rejoinSessionId };\n\n } else {\n throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, `session expired: ${rejoinSessionId}`);\n\n }\n\n } else if (!room.locked) {\n return reserveSeatFor(room, clientOptions);\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" is locked`);\n\n }\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" not found`);\n }\n\n}\n\n/**\n * Perform a query for all cached rooms\n */\nexport async function query(conditions: Partial<IRoomListingData> = {}) {\n return await driver.find(conditions);\n}\n\n/**\n * Find for a public and unlocked room available\n */\nexport async function findOneRoomAvailable(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n return await awaitRoomAvailable(roomName, async () => {\n const handler = handlers[roomName];\n if (!handler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const roomQuery = driver.findOne({\n locked: false,\n name: roomName,\n private: false,\n ...handler.getFilterOptions(clientOptions),\n });\n\n if (handler.sortOptions) {\n roomQuery.sort(handler.sortOptions);\n }\n\n return await roomQuery;\n });\n}\n\n/**\n * Call a method or return a property on a remote room.\n */\nexport async function remoteRoomCall<R= any>(\n roomId: string,\n method: string,\n args?: any[],\n rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,\n): Promise<R> {\n const room = rooms[roomId];\n\n if (!room) {\n try {\n return await requestFromIPC<R>(presence, getRoomChannel(roomId), method, args);\n\n } catch (e) {\n const request = `${method}${args && ' with args ' + JSON.stringify(args) || ''}`;\n throw new ServerError(\n ErrorCode.MATCHMAKE_UNHANDLED,\n `remote room (${roomId}) timed out, requesting \"${request}\". (${rejectionTimeout}ms exceeded)`,\n );\n }\n\n } else {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : (await room[method].apply(room, args));\n }\n}\n\nexport function defineRoomType<T extends Type<Room>>(\n name: string,\n klass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n) {\n const registeredHandler = new RegisteredHandler(klass, defaultOptions);\n\n handlers[name] = registeredHandler;\n\n cleanupStaleRooms(name);\n\n return registeredHandler;\n}\n\nexport function removeRoomType(name: string) {\n delete handlers[name];\n cleanupStaleRooms(name);\n}\n\nexport function hasHandler(name: string) {\n return handlers[ name ] !== undefined;\n}\n\n/**\n * Create a room\n */\nexport async function createRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const roomsSpawnedByProcessId = await presence.hgetall(getRoomCountKey());\n\n const processIdWithFewerRooms = (\n Object.keys(roomsSpawnedByProcessId).sort((p1, p2) => {\n return (Number(roomsSpawnedByProcessId[p1]) > Number(roomsSpawnedByProcessId[p2]))\n ? 1\n : -1;\n })[0]\n ) || processId;\n\n if (processIdWithFewerRooms === processId) {\n // create the room on this process!\n return await handleCreateRoom(roomName, clientOptions);\n\n } else {\n // ask other process to create the room!\n let room: RoomListingData;\n\n try {\n room = await requestFromIPC<RoomListingData>(\n presence,\n getProcessChannel(processIdWithFewerRooms),\n undefined,\n [roomName, clientOptions],\n REMOTE_ROOM_SHORT_TIMEOUT,\n );\n\n } catch (e) {\n // if other process failed to respond, create the room on this process\n debugAndPrintError(e);\n room = await handleCreateRoom(roomName, clientOptions);\n }\n\n return room;\n }\n}\n\nasync function handleCreateRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const registeredHandler = handlers[roomName];\n\n if (!registeredHandler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const room = new registeredHandler.klass();\n\n // set room public attributes\n room.roomId = generateId();\n room.roomName = roomName;\n room.presence = presence;\n\n // create a RoomCache reference.\n room.listing = driver.createInstance({\n name: roomName,\n processId,\n ...registeredHandler.getFilterOptions(clientOptions),\n });\n\n if (room.onCreate) {\n try {\n await room.onCreate(merge({}, clientOptions, registeredHandler.options));\n\n // increment amount of rooms this process is handling\n presence.hincrby(getRoomCountKey(), processId, 1);\n\n } catch (e) {\n debugAndPrintError(e);\n throw new ServerError(\n e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n e.message,\n );\n }\n }\n\n room.internalState = RoomInternalState.CREATED;\n\n room.listing.roomId = room.roomId;\n room.listing.maxClients = room.maxClients;\n\n // imediatelly ask client to join the room\n debugMatchMaking('spawning \\'%s\\', roomId: %s, processId: %s', roomName, room.roomId, processId);\n\n room._events.on('lock', lockRoom.bind(this, room));\n room._events.on('unlock', unlockRoom.bind(this, room));\n room._events.on('join', onClientJoinRoom.bind(this, room));\n room._events.on('leave', onClientLeaveRoom.bind(this, room));\n room._events.once('dispose', disposeRoom.bind(this, roomName, room));\n room._events.once('disconnect', () => room._events.removeAllListeners());\n\n // room always start unlocked\n await createRoomReferences(room, true);\n await room.listing.save();\n\n registeredHandler.emit('create', room);\n\n return room.listing;\n}\n\nexport function getRoomById(roomId: string) {\n return rooms[roomId];\n}\n\n/**\n * Disconnects every client on every room in the current process.\n */\nexport function disconnectAll() {\n const promises: Array<Promise<any>> = [];\n\n for (const roomId in rooms) {\n if (!rooms.hasOwnProperty(roomId)) { continue; }\n promises.push(rooms[roomId].disconnect());\n }\n\n return promises;\n}\n\nexport function gracefullyShutdown(): Promise<any> {\n if (isGracefullyShuttingDown) {\n return Promise.reject('already_shutting_down');\n }\n\n isGracefullyShuttingDown = true;\n\n debugMatchMaking(`${processId} is shutting down!`);\n\n // remove processId from room count key\n presence.hdel(getRoomCountKey(), processId);\n\n // unsubscribe from process id channel\n presence.unsubscribe(getProcessChannel());\n\n return Promise.all(disconnectAll());\n}\n\n/**\n * Reserve a seat for a client in a room\n */\nexport async function reserveSeatFor(room: RoomListingData, options: any) {\n const sessionId: string = generateId();\n\n debugMatchMaking(\n 'reserving seat. sessionId: \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'',\n sessionId, room.roomId, processId,\n );\n\n let successfulSeatReservation: boolean;\n\n try {\n successfulSeatReservation = await remoteRoomCall(room.roomId, '_reserveSeat', [sessionId, options]);\n\n } catch (e) {\n debugMatchMaking(e);\n successfulSeatReservation = false;\n }\n\n if (!successfulSeatReservation) {\n throw new SeatReservationError(`${room.roomId} is already full.`);\n }\n\n return { room, sessionId };\n}\n\nasync function cleanupStaleRooms(roomName: string) {\n //\n // clean-up possibly stale room ids\n // (ungraceful shutdowns using Redis can result on stale room ids still on memory.)\n //\n const cachedRooms = await driver.find({ name: roomName }, { _id: 1 });\n\n // remove connecting counts\n await presence.del(getHandlerConcurrencyKey(roomName));\n\n await Promise.all(cachedRooms.map(async (room) => {\n try {\n // use hardcoded short timeout for cleaning up stale rooms.\n await remoteRoomCall(room.roomId, 'roomId');\n\n } catch (e) {\n debugMatchMaking(`cleaning up stale room '${roomName}', roomId: ${room.roomId}`);\n room.remove();\n }\n }));\n}\n\nasync function createRoomReferences(room: Room, init: boolean = false): Promise<boolean> {\n rooms[room.roomId] = room;\n\n if (init) {\n await subscribeIPC(\n presence,\n processId,\n getRoomChannel(room.roomId),\n (method, args) => {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : room[method].apply(room, args);\n },\n );\n }\n\n return true;\n}\n\nasync function awaitRoomAvailable(roomToJoin: string, callback: Function): Promise<RoomListingData> {\n return new Promise(async (resolve, reject) => {\n const concurrencyKey = getHandlerConcurrencyKey(roomToJoin);\n const concurrency = await presence.incr(concurrencyKey) - 1;\n\n // avoid having too long timeout if 10+ clients ask to join at the same time\n const concurrencyTimeout = Math.min(concurrency * 100, REMOTE_ROOM_SHORT_TIMEOUT);\n\n if (concurrency > 0) {\n debugMatchMaking(\n 'receiving %d concurrent requests for joining \\'%s\\' (waiting %d ms)',\n concurrency, roomToJoin, concurrencyTimeout,\n );\n }\n\n setTimeout(async () => {\n try {\n const result = await callback();\n resolve(result);\n\n } catch (e) {\n reject(e);\n\n } finally {\n await presence.decr(concurrencyKey);\n }\n }, concurrencyTimeout);\n });\n}\n\nfunction onClientJoinRoom(room: Room, client: Client) {\n handlers[room.roomName].emit('join', room, client);\n}\n\nfunction onClientLeaveRoom(room: Room, client: Client, willDispose: boolean) {\n handlers[room.roomName].emit('leave', room, client, willDispose);\n}\n\nfunction lockRoom(room: Room): void {\n // emit public event on registered handler\n handlers[room.roomName].emit('lock', room);\n}\n\nasync function unlockRoom(room: Room) {\n if (await createRoomReferences(room)) {\n // emit public event on registered handler\n handlers[room.roomName].emit('unlock', room);\n }\n}\n\nasync function disposeRoom(roomName: string, room: Room) {\n debugMatchMaking('disposing \\'%s\\' (%s) on processId \\'%s\\'', roomName, room.roomId, processId);\n\n // decrease amount of rooms this process is handling\n if (!isGracefullyShuttingDown) {\n presence.hincrby(getRoomCountKey(), processId, -1);\n }\n\n // remove from room listing (already removed if `disconnect()` has been called)\n if (room.internalState !== RoomInternalState.DISCONNECTING) {\n await room.listing.remove();\n }\n\n // emit disposal on registered session handler\n handlers[roomName].emit('dispose', room);\n\n // remove concurrency key\n presence.del(getHandlerConcurrencyKey(roomName));\n\n // unsubscribe from remote connections\n presence.unsubscribe(getRoomChannel(room.roomId));\n\n // remove actual room reference\n delete rooms[room.roomId];\n}\n\n//\n// Presence keys\n//\n\nfunction getRoomChannel(roomId: string) {\n return `$${roomId}`;\n}\n\nfunction getHandlerConcurrencyKey(name: string) {\n return `c:${name}`;\n}\n\nfunction getProcessChannel(id: string = processId) {\n return `p:${id}`;\n}\n\nfunction getRoomCountKey() {\n return 'roomcount';\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MatchMaker.mjs","sources":["../src/MatchMaker.ts"],"sourcesContent":["import { ErrorCode } from './Protocol';\n\nimport { requestFromIPC, subscribeIPC } from './IPC';\nimport { generateId, merge, REMOTE_ROOM_SHORT_TIMEOUT, retry } from './Utils';\n\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Room, RoomInternalState } from './Room';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { Presence } from './presence/Presence';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport { SeatReservationError } from './errors/SeatReservationError';\nimport { ServerError } from './errors/ServerError';\n\nimport { IRoomListingData, MatchMakerDriver, RoomListingData, LocalDriver } from './matchmaker/driver';\nimport * as controller from './matchmaker/controller';\n\nimport { Client } from './Transport';\nimport { Type } from './types';\n\nexport { MatchMakerDriver, controller };\n\nexport type ClientOptions = any;\n\nexport interface SeatReservation {\n sessionId: string;\n room: RoomListingData;\n}\n\nconst handlers: {[id: string]: RegisteredHandler} = {};\nconst rooms: {[roomId: string]: Room} = {};\n\nexport let processId: string;\nexport let presence: Presence;\nexport let driver: MatchMakerDriver;\n\nlet isGracefullyShuttingDown: boolean;\n\nexport function setup(_presence?: Presence, _driver?: MatchMakerDriver, _processId?: string) {\n presence = _presence || new LocalPresence();\n driver = _driver || new LocalDriver();\n processId = _processId;\n isGracefullyShuttingDown = false;\n\n /**\n * Subscribe to remote `handleCreateRoom` calls.\n */\n subscribeIPC(presence, processId, getProcessChannel(), (_, args) => {\n return handleCreateRoom.apply(undefined, args);\n });\n\n presence.hset(getRoomCountKey(), processId, '0');\n}\n\n/**\n * Join or create into a room and return seat reservation\n */\nexport async function joinOrCreate(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n let room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n room = await createRoom(roomName, clientOptions);\n }\n\n return await reserveSeatFor(room, clientOptions);\n }, 5, [SeatReservationError]);\n}\n\n/**\n * Create a room and return seat reservation\n */\nexport async function create(roomName: string, clientOptions: ClientOptions = {}) {\n const room = await createRoom(roomName, clientOptions);\n return reserveSeatFor(room, clientOptions);\n}\n\n/**\n * Join a room and return seat reservation\n */\nexport async function join(roomName: string, clientOptions: ClientOptions = {}) {\n return await retry<Promise<SeatReservation>>(async () => {\n const room = await findOneRoomAvailable(roomName, clientOptions);\n\n if (!room) {\n throw new ServerError(ErrorCode.MATCHMAKE_INVALID_CRITERIA, `no rooms found with provided criteria`);\n }\n\n return reserveSeatFor(room, clientOptions);\n });\n}\n\n/**\n * Join a room by id and return seat reservation\n */\nexport async function joinById(roomId: string, clientOptions: ClientOptions = {}) {\n const room = await driver.findOne({ roomId });\n\n if (room) {\n const rejoinSessionId = clientOptions.sessionId;\n\n if (rejoinSessionId) {\n // handle re-connection!\n const hasReservedSeat = await remoteRoomCall(room.roomId, 'hasReservedSeat', [rejoinSessionId]);\n\n if (hasReservedSeat) {\n return { room, sessionId: rejoinSessionId };\n\n } else {\n throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, `session expired: ${rejoinSessionId}`);\n\n }\n\n } else if (!room.locked) {\n return reserveSeatFor(room, clientOptions);\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" is locked`);\n\n }\n\n } else {\n throw new ServerError( ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" not found`);\n }\n\n}\n\n/**\n * Perform a query for all cached rooms\n */\nexport async function query(conditions: Partial<IRoomListingData> = {}) {\n return await driver.find(conditions);\n}\n\n/**\n * Find for a public and unlocked room available\n */\nexport async function findOneRoomAvailable(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n return await awaitRoomAvailable(roomName, async () => {\n const handler = handlers[roomName];\n if (!handler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const roomQuery = driver.findOne({\n locked: false,\n name: roomName,\n private: false,\n ...handler.getFilterOptions(clientOptions),\n });\n\n if (handler.sortOptions) {\n roomQuery.sort(handler.sortOptions);\n }\n\n return await roomQuery;\n });\n}\n\n/**\n * Call a method or return a property on a remote room.\n */\nexport async function remoteRoomCall<R= any>(\n roomId: string,\n method: string,\n args?: any[],\n rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,\n): Promise<R> {\n const room = rooms[roomId];\n\n if (!room) {\n try {\n return await requestFromIPC<R>(presence, getRoomChannel(roomId), method, args);\n\n } catch (e) {\n const request = `${method}${args && ' with args ' + JSON.stringify(args) || ''}`;\n throw new ServerError(\n ErrorCode.MATCHMAKE_UNHANDLED,\n `remote room (${roomId}) timed out, requesting \"${request}\". (${rejectionTimeout}ms exceeded)`,\n );\n }\n\n } else {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : (await room[method].apply(room, args && args.map((arg) => JSON.parse(JSON.stringify(arg)))));\n }\n}\n\nexport function defineRoomType<T extends Type<Room>>(\n name: string,\n klass: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n) {\n const registeredHandler = new RegisteredHandler(klass, defaultOptions);\n\n handlers[name] = registeredHandler;\n\n cleanupStaleRooms(name);\n\n return registeredHandler;\n}\n\nexport function removeRoomType(name: string) {\n delete handlers[name];\n cleanupStaleRooms(name);\n}\n\nexport function hasHandler(name: string) {\n return handlers[ name ] !== undefined;\n}\n\n/**\n * Create a room\n */\nexport async function createRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const roomsSpawnedByProcessId = await presence.hgetall(getRoomCountKey());\n\n const processIdWithFewerRooms = (\n Object.keys(roomsSpawnedByProcessId).sort((p1, p2) => {\n return (Number(roomsSpawnedByProcessId[p1]) > Number(roomsSpawnedByProcessId[p2]))\n ? 1\n : -1;\n })[0]\n ) || processId;\n\n if (processIdWithFewerRooms === processId) {\n // create the room on this process!\n return await handleCreateRoom(roomName, clientOptions);\n\n } else {\n // ask other process to create the room!\n let room: RoomListingData;\n\n try {\n room = await requestFromIPC<RoomListingData>(\n presence,\n getProcessChannel(processIdWithFewerRooms),\n undefined,\n [roomName, clientOptions],\n REMOTE_ROOM_SHORT_TIMEOUT,\n );\n\n } catch (e) {\n // if other process failed to respond, create the room on this process\n debugAndPrintError(e);\n room = await handleCreateRoom(roomName, clientOptions);\n }\n\n return room;\n }\n}\n\nasync function handleCreateRoom(roomName: string, clientOptions: ClientOptions): Promise<RoomListingData> {\n const registeredHandler = handlers[roomName];\n\n if (!registeredHandler) {\n throw new ServerError( ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n }\n\n const room = new registeredHandler.klass();\n\n // set room public attributes\n room.roomId = generateId();\n room.roomName = roomName;\n room.presence = presence;\n\n // create a RoomCache reference.\n room.listing = driver.createInstance({\n name: roomName,\n processId,\n ...registeredHandler.getFilterOptions(clientOptions),\n });\n\n if (room.onCreate) {\n try {\n await room.onCreate(merge({}, clientOptions, registeredHandler.options));\n\n // increment amount of rooms this process is handling\n presence.hincrby(getRoomCountKey(), processId, 1);\n\n } catch (e) {\n debugAndPrintError(e);\n throw new ServerError(\n e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n e.message,\n );\n }\n }\n\n room.internalState = RoomInternalState.CREATED;\n\n room.listing.roomId = room.roomId;\n room.listing.maxClients = room.maxClients;\n\n // imediatelly ask client to join the room\n debugMatchMaking('spawning \\'%s\\', roomId: %s, processId: %s', roomName, room.roomId, processId);\n\n room._events.on('lock', lockRoom.bind(this, room));\n room._events.on('unlock', unlockRoom.bind(this, room));\n room._events.on('join', onClientJoinRoom.bind(this, room));\n room._events.on('leave', onClientLeaveRoom.bind(this, room));\n room._events.once('dispose', disposeRoom.bind(this, roomName, room));\n room._events.once('disconnect', () => room._events.removeAllListeners());\n\n // room always start unlocked\n await createRoomReferences(room, true);\n await room.listing.save();\n\n registeredHandler.emit('create', room);\n\n return room.listing;\n}\n\nexport function getRoomById(roomId: string) {\n return rooms[roomId];\n}\n\n/**\n * Disconnects every client on every room in the current process.\n */\nexport function disconnectAll() {\n const promises: Array<Promise<any>> = [];\n\n for (const roomId in rooms) {\n if (!rooms.hasOwnProperty(roomId)) { continue; }\n promises.push(rooms[roomId].disconnect());\n }\n\n return promises;\n}\n\nexport function gracefullyShutdown(): Promise<any> {\n if (isGracefullyShuttingDown) {\n return Promise.reject('already_shutting_down');\n }\n\n isGracefullyShuttingDown = true;\n\n debugMatchMaking(`${processId} is shutting down!`);\n\n // remove processId from room count key\n presence.hdel(getRoomCountKey(), processId);\n\n // unsubscribe from process id channel\n presence.unsubscribe(getProcessChannel());\n\n return Promise.all(disconnectAll());\n}\n\n/**\n * Reserve a seat for a client in a room\n */\nexport async function reserveSeatFor(room: RoomListingData, options: any) {\n const sessionId: string = generateId();\n\n debugMatchMaking(\n 'reserving seat. sessionId: \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'',\n sessionId, room.roomId, processId,\n );\n\n let successfulSeatReservation: boolean;\n\n try {\n successfulSeatReservation = await remoteRoomCall(room.roomId, '_reserveSeat', [sessionId, options]);\n\n } catch (e) {\n debugMatchMaking(e);\n successfulSeatReservation = false;\n }\n\n if (!successfulSeatReservation) {\n throw new SeatReservationError(`${room.roomId} is already full.`);\n }\n\n return { room, sessionId };\n}\n\nasync function cleanupStaleRooms(roomName: string) {\n //\n // clean-up possibly stale room ids\n // (ungraceful shutdowns using Redis can result on stale room ids still on memory.)\n //\n const cachedRooms = await driver.find({ name: roomName }, { _id: 1 });\n\n // remove connecting counts\n await presence.del(getHandlerConcurrencyKey(roomName));\n\n await Promise.all(cachedRooms.map(async (room) => {\n try {\n // use hardcoded short timeout for cleaning up stale rooms.\n await remoteRoomCall(room.roomId, 'roomId');\n\n } catch (e) {\n debugMatchMaking(`cleaning up stale room '${roomName}', roomId: ${room.roomId}`);\n room.remove();\n }\n }));\n}\n\nasync function createRoomReferences(room: Room, init: boolean = false): Promise<boolean> {\n rooms[room.roomId] = room;\n\n if (init) {\n await subscribeIPC(\n presence,\n processId,\n getRoomChannel(room.roomId),\n (method, args) => {\n return (!args && typeof (room[method]) !== 'function')\n ? room[method]\n : room[method].apply(room, args);\n },\n );\n }\n\n return true;\n}\n\nasync function awaitRoomAvailable(roomToJoin: string, callback: Function): Promise<RoomListingData> {\n return new Promise(async (resolve, reject) => {\n const concurrencyKey = getHandlerConcurrencyKey(roomToJoin);\n const concurrency = await presence.incr(concurrencyKey) - 1;\n\n // avoid having too long timeout if 10+ clients ask to join at the same time\n const concurrencyTimeout = Math.min(concurrency * 100, REMOTE_ROOM_SHORT_TIMEOUT);\n\n if (concurrency > 0) {\n debugMatchMaking(\n 'receiving %d concurrent requests for joining \\'%s\\' (waiting %d ms)',\n concurrency, roomToJoin, concurrencyTimeout,\n );\n }\n\n setTimeout(async () => {\n try {\n const result = await callback();\n resolve(result);\n\n } catch (e) {\n reject(e);\n\n } finally {\n await presence.decr(concurrencyKey);\n }\n }, concurrencyTimeout);\n });\n}\n\nfunction onClientJoinRoom(room: Room, client: Client) {\n handlers[room.roomName].emit('join', room, client);\n}\n\nfunction onClientLeaveRoom(room: Room, client: Client, willDispose: boolean) {\n handlers[room.roomName].emit('leave', room, client, willDispose);\n}\n\nfunction lockRoom(room: Room): void {\n // emit public event on registered handler\n handlers[room.roomName].emit('lock', room);\n}\n\nasync function unlockRoom(room: Room) {\n if (await createRoomReferences(room)) {\n // emit public event on registered handler\n handlers[room.roomName].emit('unlock', room);\n }\n}\n\nasync function disposeRoom(roomName: string, room: Room) {\n debugMatchMaking('disposing \\'%s\\' (%s) on processId \\'%s\\'', roomName, room.roomId, processId);\n\n // decrease amount of rooms this process is handling\n if (!isGracefullyShuttingDown) {\n presence.hincrby(getRoomCountKey(), processId, -1);\n }\n\n // remove from room listing (already removed if `disconnect()` has been called)\n if (room.internalState !== RoomInternalState.DISCONNECTING) {\n await room.listing.remove();\n }\n\n // emit disposal on registered session handler\n handlers[roomName].emit('dispose', room);\n\n // remove concurrency key\n presence.del(getHandlerConcurrencyKey(roomName));\n\n // unsubscribe from remote connections\n presence.unsubscribe(getRoomChannel(room.roomId));\n\n // remove actual room reference\n delete rooms[room.roomId];\n}\n\n//\n// Presence keys\n//\n\nfunction getRoomChannel(roomId: string) {\n return `$${roomId}`;\n}\n\nfunction getHandlerConcurrencyKey(name: string) {\n return `c:${name}`;\n}\n\nfunction getProcessChannel(id: string = processId) {\n return `p:${id}`;\n}\n\nfunction getRoomCountKey() {\n return 'roomcount';\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/core",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.36",
|
|
4
4
|
"description": "Multiplayer Framework for Node.js.",
|
|
5
5
|
"input": "./src/index.ts",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "91bf2cb492d33c314c2ccb90ee8d3c7dfad7ad58"
|
|
49
49
|
}
|