{
  "version": 3,
  "sources": ["../src/MatchMaker.ts"],
  "sourcesContent": ["import { EventEmitter } from 'events';\n\nimport { requestFromIPC, subscribeIPC, subscribeWithTimeout } from './IPC.ts';\n\nimport { type Type, Deferred, generateId, merge, retry, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME, REMOTE_ROOM_SHORT_TIMEOUT, type MethodName, type ExtractMethodOrPropertyType } from './utils/Utils.ts';\nimport { isDevMode, cacheRoomHistory, getPreviousProcessId, getRoomRestoreListKey, reloadFromCache } from './utils/DevMode.ts';\n\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler.ts';\nimport { type OnCreateOptions, Room, RoomInternalState } from './Room.ts';\n\nimport { LocalPresence } from './presence/LocalPresence.ts';\nimport { createScopedPresence, type Presence } from './presence/Presence.ts';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug.ts';\nimport { SeatReservationError } from './errors/SeatReservationError.ts';\nimport { ServerError } from './errors/ServerError.ts';\n\nimport { type IRoomCache, type MatchMakerDriver, type SortOptions, LocalDriver } from './matchmaker/LocalDriver/LocalDriver.ts';\nimport { controller } from './matchmaker/controller.ts';\nimport * as stats from './Stats.ts';\n\nimport { logger } from './Logger.ts';\nimport type { AuthContext, Client } from './Transport.ts';\nimport { getLockId, initializeRoomCache, type ExtractRoomCacheMetadata } from './matchmaker/driver.ts';\n\nimport { type ISeatReservation, CloseCode, ErrorCode } from '@colyseus/shared-types';\nimport { getDefaultDriver, getDefaultPresence, getDefaultPublicAddress } from './utils/Env.ts';\nexport type { ISeatReservation, ExtractRoomCacheMetadata };\n\nexport { controller, stats, type MatchMakerDriver };\n\nexport type ClientOptions = any;\nexport type SelectProcessIdCallback = (roomName: string, clientOptions: ClientOptions) => Promise<string>;\n\nconst handlers: {[id: string]: RegisteredHandler} = {};\nconst rooms: {[roomId: string]: Room} = {};\nconst events = new EventEmitter();\n\nexport let publicAddress: string;\nexport let processId: string;\nexport let presence: Presence;\nexport let driver: MatchMakerDriver;\n\n/**\n * Function to select the processId to create the room on.\n * By default, returns the process with least amount of rooms created.\n * @returns The processId to create the room on.\n */\nexport let selectProcessIdToCreateRoom: SelectProcessIdCallback = async function () {\n  return (await stats.fetchAll())\n    .sort((p1, p2) => p1.roomCount > p2.roomCount ? 1 : -1)[0]?.processId || processId;\n};\n\n/**\n * Whether health checks are enabled or not. (default: true)\n *\n * Health checks are automatically performed on theses scenarios:\n * - At startup, to check for leftover/invalid processId's\n * - When a remote room creation request times out\n * - When a remote seat reservation request times out\n */\nlet enableHealthChecks: boolean = true;\nexport function setHealthChecksEnabled(value: boolean) {\n  enableHealthChecks = value;\n}\n\nexport let onReady: Deferred = new Deferred(); // onReady needs to be immediately available to @colyseus/auth integration.\n\nexport const MatchMakerState = {\n  INITIALIZING: 0,\n  READY: 1,\n  SHUTTING_DOWN: 2,\n} as const;\nexport type MatchMakerState = (typeof MatchMakerState)[keyof typeof MatchMakerState];\n\n/**\n * Internal MatchMaker state\n */\nexport let state: MatchMakerState;\n\n/**\n * @private\n */\nexport async function setup(\n  _presence?: Presence,\n  _driver?: MatchMakerDriver,\n  _publicAddress?: string,\n  _selectProcessIdToCreateRoom?: SelectProcessIdCallback,\n) {\n  if (onReady === undefined) {\n    //\n    // for testing purposes only: onReady is turned into undefined on shutdown\n    // (needs refactoring.)\n    //\n    onReady = new Deferred();\n  }\n\n  state = MatchMakerState.INITIALIZING;\n\n  presence = _presence || await getDefaultPresence();\n  driver = _driver || await getDefaultDriver();\n  publicAddress = _publicAddress || getDefaultPublicAddress();\n\n  stats.reset(false);\n\n  // devMode: try to retrieve previous processId\n  if (isDevMode) { processId = await getPreviousProcessId(); }\n\n  // ensure processId is set\n  if (!processId) { processId = generateId(); }\n\n  /**\n   * Override default `selectProcessIdToCreateRoom` function.\n   */\n  if (_selectProcessIdToCreateRoom) {\n    selectProcessIdToCreateRoom = _selectProcessIdToCreateRoom;\n  }\n\n  // boot driver if necessary (e.g. RedisDriver/PostgresDriver)\n  if (driver.boot) {\n    await driver.boot();\n  }\n\n  onReady.resolve();\n}\n\n/**\n * - Accept receiving remote room creation requests\n * - Check for leftover/invalid processId's on startup\n * @private\n */\nexport async function accept(isStandalone: boolean = false) {\n  await onReady; // make sure \"processId\" is available\n\n  /**\n   * Skip setting up IPC and health checks if this process is running as a\n   * standalone match-maker. \n   * \n   * When in \"standalone\" mode, this process will not spawn rooms and will only\n   * be responsible for matchmaking.\n   */\n  if (isStandalone) {\n    state = MatchMakerState.READY;\n    return; \n  }\n\n  /**\n   * Process-level subscription\n   * - handle remote process healthcheck\n   * - handle remote room creation\n   */\n  await subscribeIPC(presence, getProcessChannel(), (method: string, args: any) => {\n    if (method === 'healthcheck') {\n      // health check for this processId\n      return true;\n\n    } else {\n      // handle room creation\n      return handleCreateRoom.apply(undefined, args);\n    }\n  });\n\n  /**\n   * Check for leftover/invalid processId's on startup\n   */\n  if (enableHealthChecks) {\n    await healthCheckAllProcesses();\n\n    /*\n     * persist processId every 1 minute\n     *\n     * FIXME: this is a workaround in case this `processId` gets excluded\n     * (`stats.excludeProcess()`) by mistake due to health-check failure\n     */\n    stats.setAutoPersistInterval();\n  }\n\n  state = MatchMakerState.READY;\n\n  await stats.persist();\n\n  if (isDevMode) {\n    await reloadFromCache();\n  }\n}\n\n/**\n * Join or create into a room and return seat reservation\n */\nexport async function joinOrCreate(roomName: string, clientOptions: ClientOptions = {}, authContext?: AuthContext) {\n  return await retry<Promise<ISeatReservation>>(async () => {\n    const authData = await callOnAuth(roomName, clientOptions, authContext);\n    let room: IRoomCache = await findOneRoomAvailable(roomName, clientOptions);\n\n    if (!room) {\n      const handler = getHandler(roomName);\n      const filterOptions = handler.getFilterOptions(clientOptions);\n      const concurrencyKey = getLockId(filterOptions);\n\n      //\n      // Prevent multiple rooms of same filter from being created concurrently\n      //\n      await concurrentJoinOrCreateRoomLock(handler, concurrencyKey, async (roomId?: string) => {\n        if (roomId) {\n          room = await driver.findOne({ roomId })\n        }\n\n        // If the room is not found or is already locked, try to find a new one\n        if (!room || room.locked) {\n          room = await findOneRoomAvailable(roomName, clientOptions);\n        }\n\n        if (!room) {\n          //\n          // TODO [?]\n          //    should we expose the \"creator\" auth data of the room during `onCreate()`?\n          //    it would be useful, though it could be accessed via `onJoin()` for now.\n          //\n          room = await createRoom(roomName, clientOptions);\n\n          // Notify waiting concurrent requests about the new room\n          presence.publish(`concurrent:${handler.name}:${concurrencyKey}`, room.roomId);\n        }\n\n        return room;\n      });\n    }\n\n    return await reserveSeatFor(room, clientOptions, authData);\n  }, 5, [SeatReservationError]);\n}\n\n/**\n * Create a room and return seat reservation\n */\nexport async function create(roomName: string, clientOptions: ClientOptions = {}, authContext?: AuthContext) {\n  const authData = await callOnAuth(roomName, clientOptions, authContext);\n  const room = await createRoom(roomName, clientOptions);\n  return reserveSeatFor(room, clientOptions, authData);\n}\n\n/**\n * Join a room and return seat reservation\n */\nexport async function join(roomName: string, clientOptions: ClientOptions = {}, authContext?: AuthContext) {\n  return await retry<Promise<ISeatReservation>>(async () => {\n    const authData = await callOnAuth(roomName, clientOptions, authContext);\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, authData);\n  });\n}\n\n/**\n * Join a room by id and return seat reservation\n */\nexport async function reconnect(roomId: string, clientOptions: ClientOptions = {}) {\n  const room = await driver.findOne({ roomId });\n  if (!room) {\n    // TODO: support a \"logLevel\" out of the box?\n    if (process.env.NODE_ENV !== 'production') {\n      logger.info(`\u274C room \"${roomId}\" has been disposed. Did you miss .allowReconnection()?\\n\uD83D\uDC49 https://docs.colyseus.io/room#allow-reconnection`);\n    }\n\n    throw new ServerError(ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" has been disposed.`);\n  }\n\n  // check for reconnection\n  const reconnectionToken = clientOptions.reconnectionToken;\n  if (!reconnectionToken) { throw new ServerError(ErrorCode.MATCHMAKE_UNHANDLED, `'reconnectionToken' must be provided for reconnection.`); }\n\n  // respond to re-connection!\n  const sessionId = await remoteRoomCall(room.roomId, 'checkReconnectionToken', [reconnectionToken]);\n  if (sessionId) {\n    return buildSeatReservation(room, sessionId);\n\n  } else {\n    // TODO: support a \"logLevel\" out of the box?\n    if (process.env.NODE_ENV !== 'production') {\n      logger.info(`\u274C reconnection token invalid or expired. Did you miss .allowReconnection()?\\n\uD83D\uDC49 https://docs.colyseus.io/room#allow-reconnection`);\n    }\n    throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, `reconnection token invalid or expired.`);\n  }\n}\n\n/**\n * Join a room by id and return client seat reservation. An exception is thrown if a room is not found for roomId.\n *\n * @param roomId - The Id of the specific room instance.\n * @param clientOptions - Options for the client seat reservation (for `onJoin`/`onAuth`)\n * @param authContext - Optional authentication token\n *\n * @returns Promise<SeatReservation> - A promise which contains `sessionId` and `IRoomCache`.\n */\nexport async function joinById(roomId: string, clientOptions: ClientOptions = {}, authContext?: AuthContext) {\n  const room = await driver.findOne({ roomId });\n\n  if (!room) {\n    throw new ServerError(ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" not found`);\n\n  } else if (room.locked) {\n    throw new ServerError(ErrorCode.MATCHMAKE_INVALID_ROOM_ID, `room \"${roomId}\" is locked`);\n  }\n\n  const authData = await callOnAuth(room.name, clientOptions, authContext);\n\n  return reserveSeatFor(room, clientOptions, authData);\n}\n\n/**\n * Perform a query for all cached rooms\n */\nexport async function query<T extends Room = any>(\n  conditions: Partial<IRoomCache & ExtractRoomCacheMetadata<T>> = {},\n  sortOptions?: SortOptions,\n) {\n  return await driver.query<T>(conditions, sortOptions);\n}\n\n/**\n * Find for a public and unlocked room available.\n *\n * @param roomName - The Id of the specific room.\n * @param filterOptions - Filter options.\n * @param sortOptions - Sorting options.\n *\n * @returns Promise<IRoomCache> - A promise contaning an object which includes room metadata and configurations.\n */\nexport async function findOneRoomAvailable(\n  roomName: string,\n  filterOptions: ClientOptions,\n  additionalSortOptions?: SortOptions,\n) {\n  const handler = getHandler(roomName);\n  const sortOptions = Object.assign({}, handler.sortOptions ?? {});\n\n  if (additionalSortOptions) {\n    Object.assign(sortOptions, additionalSortOptions);\n  }\n\n  return await driver.findOne({\n    locked: false,\n    name: roomName,\n    private: false,\n    ...handler.getFilterOptions(filterOptions),\n  }, sortOptions);\n}\n\n/**\n * Call a method or return a property on a remote room.\n *\n * @param roomId - The Id of the specific room instance.\n * @param method - Method or attribute to call or retrive.\n * @param args - Array of arguments for the method\n *\n * @returns Promise<any> - Returned value from the called or retrieved method/attribute.\n */\nexport async function remoteRoomCall<TRoom = Room>(\n  roomId: string,\n  method: keyof TRoom,\n  args?: any[],\n  rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT,\n): Promise<ExtractMethodOrPropertyType<TRoom, typeof method>> {\n  const room = rooms[roomId] as TRoom;\n\n  if (!room) {\n    try {\n      return await requestFromIPC(presence, getRoomChannel(roomId), method as string, args, rejectionTimeout);\n\n    } catch (e: any) {\n\n      //\n      // the room cache from an unavailable process might've been used here.\n      // perform a health-check on the process before proceeding.\n      // (this is a broken state when a process wasn't gracefully shut down)\n      //\n      if (method === '_reserveSeat' && e.message === \"ipc_timeout\") {\n        throw e;\n      }\n\n      // TODO: for 1.0, consider always throwing previous error directly.\n\n      const request = `${String(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 as string]\n        : (await room[method as string].apply(room, args && JSON.parse(JSON.stringify(args))));\n  }\n}\n\nexport function defineRoomType<T extends Type<Room>>(\n  roomName: string,\n  klass: T,\n  defaultOptions?: OnCreateOptions<T>,\n): RegisteredHandler<InstanceType<T>> {\n  const registeredHandler = new RegisteredHandler(klass, defaultOptions) as unknown as RegisteredHandler<InstanceType<T>>;\n  registeredHandler.name = roomName;\n\n  handlers[roomName] = registeredHandler;\n\n  if (klass.prototype['onAuth'] !== Room.prototype['onAuth']) {\n    // TODO: soft-deprecate instance level `onAuth` on 0.16\n    // logger.warn(\"DEPRECATION WARNING: onAuth() at the instance level will be deprecated soon. Please use static onAuth() instead.\");\n\n    if (klass['onAuth'] !== Room['onAuth']) {\n      logger.info(`\u274C \"${roomName}\"'s onAuth() defined at the instance level will be ignored.`);\n    }\n  }\n\n  return registeredHandler;\n}\n\nexport function addRoomType(handler: RegisteredHandler) {\n  handlers[handler.name] = handler;\n}\n\nexport function removeRoomType(roomName: string) {\n  delete handlers[roomName];\n}\n\nexport function getAllHandlers() {\n  return handlers;\n}\n\nexport function getHandler(roomName: string) {\n  const handler = handlers[roomName];\n\n  if (!handler) {\n    throw new ServerError(ErrorCode.MATCHMAKE_NO_HANDLER, `provided room name \"${roomName}\" not defined`);\n  }\n\n  return handler;\n}\n\nexport function getRoomClass(roomName: string): Type<Room> {\n  return handlers[roomName]?.klass;\n}\n\n\n/**\n * Creates a new room.\n *\n * @param roomName - The identifier you defined on `gameServer.define()`\n * @param clientOptions - Options for `onCreate`\n *\n * @returns Promise<IRoomCache> - A promise contaning an object which includes room metadata and configurations.\n */\nexport async function createRoom(roomName: string, clientOptions: ClientOptions): Promise<IRoomCache> {\n  //\n  // - select a process to create the room\n  // - use local processId if MatchMaker is not ready yet\n  //\n  const selectedProcessId = (state === MatchMakerState.READY)\n    ? await selectProcessIdToCreateRoom(roomName, clientOptions)\n    : processId;\n\n  let room: IRoomCache;\n  if (selectedProcessId === undefined) {\n\n    if (isDevMode && processId === undefined) {\n      //\n      // WORKAROUND: wait for processId to be available\n      // TODO: Remove this check on 1.0\n      //\n      // - This is a workaround when using matchMaker.createRoom() before the processId is available.\n      // - We need to use top-level await to retrieve processId\n      //\n      await onReady;\n      return createRoom(roomName, clientOptions);\n\n    } else {\n      throw new ServerError(ErrorCode.MATCHMAKE_UNHANDLED, `no processId available to create room ${roomName}`);\n    }\n\n  } else if (selectedProcessId === processId) {\n    // create the room on this process!\n    room = await handleCreateRoom(roomName, clientOptions);\n\n  } else {\n    // ask other process to create the room!\n    try {\n      room = await requestFromIPC<IRoomCache>(\n        presence,\n        getProcessChannel(selectedProcessId),\n        undefined,\n        [roomName, clientOptions],\n        REMOTE_ROOM_SHORT_TIMEOUT,\n      );\n\n    } catch (e: any) {\n      if (e.message === \"ipc_timeout\") {\n        debugAndPrintError(`${e.message}: create room request timed out for ${roomName} on processId ${selectedProcessId}.`);\n\n        //\n        // clean-up possibly stale process from redis.\n        // when a process disconnects ungracefully, it may leave its previous processId under \"roomcount\"\n        // if the process is still alive, it will re-add itself shortly after the load-balancer selects it again.\n        //\n        if (enableHealthChecks) {\n          await stats.excludeProcess(selectedProcessId);\n        }\n\n        // if other process failed to respond, create the room on this process\n        room = await handleCreateRoom(roomName, clientOptions);\n\n      } else {\n        // re-throw intentional exception thrown during remote onCreate()\n        throw e;\n      }\n    }\n  }\n\n  if (isDevMode) {\n    presence.hset(getRoomRestoreListKey(), room.roomId, JSON.stringify({\n      \"clientOptions\": clientOptions,\n      \"roomName\": roomName,\n      \"processId\": processId\n    }));\n  }\n\n  return room;\n}\n\nexport async function handleCreateRoom(roomName: string, clientOptions: ClientOptions, restoringRoomId?: string): Promise<IRoomCache> {\n  const handler = getHandler(roomName);\n  const room: Room = new handler.klass();\n\n  // set room public attributes\n  if (restoringRoomId && isDevMode) {\n    room.roomId = restoringRoomId;\n\n  } else {\n    room.roomId = generateId();\n  }\n\n  //\n  // Initialize .state (if set).\n  //\n  // Define getters and setters for:\n  //   - autoDispose\n  //   - patchRate\n  //\n  room['__init']();\n\n  room.roomName = roomName;\n  room.presence = createScopedPresence(room, presence);\n\n  // initialize a RoomCache instance\n  room['_listing'] = initializeRoomCache({\n    name: roomName,\n    processId,\n    ...handler.getMetadataFromOptions(clientOptions)\n  });\n\n  // assign public host\n  if (publicAddress) {\n    room['_listing'].publicAddress = publicAddress;\n  }\n\n  if (room.onCreate) {\n    try {\n      await room.onCreate(merge({}, clientOptions, handler.options));\n\n    } catch (e: any) {\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('creating room \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'', roomName, room.roomId, processId);\n\n  // increment amount of rooms this process is handling\n  stats.local.roomCount++;\n  stats.persist();\n\n  room['_events'].on('lock', lockRoom.bind(undefined, room));\n  room['_events'].on('unlock', unlockRoom.bind(undefined, room));\n  room['_events'].on('join', onClientJoinRoom.bind(undefined, room));\n  room['_events'].on('leave', onClientLeaveRoom.bind(undefined, room));\n  room['_events'].once('dispose', disposeRoom.bind(undefined, roomName, room));\n\n  if (handler.realtimeListingEnabled) {\n    room['_events'].on('visibility-change', onVisibilityChange.bind(undefined, room));\n    room['_events'].on('metadata-change', onMetadataChange.bind(undefined, room));\n  }\n\n  // when disconnect()'ing, keep only join/leave events for stat counting\n  room['_events'].once('disconnect', () => {\n    room['_events'].removeAllListeners('lock');\n    room['_events'].removeAllListeners('unlock');\n    room['_events'].removeAllListeners('dispose');\n\n    if (handler.realtimeListingEnabled) {\n      room['_events'].removeAllListeners('visibility-change');\n      room['_events'].removeAllListeners('metadata-change');\n    }\n\n    //\n    // emit \"no active rooms\" event when there are no more rooms in this process\n    // (used during graceful shutdown)\n    //\n    if (stats.local.roomCount <= 0) {\n      events.emit('no-active-rooms');\n    }\n  });\n\n  // room always start unlocked\n  await createRoomReferences(room, true);\n\n  // persist room data only if match-making is enabled\n  if (state !== MatchMakerState.SHUTTING_DOWN) {\n    await driver.persist(room['_listing'], true);\n  }\n\n  handler.emit('create', room);\n\n  return room['_listing'];\n}\n\n/**\n * Get room data by roomId.\n * This method does not return the actual room instance, use `getLocalRoomById` for that.\n */\nexport function getRoomById(roomId: string) {\n  return driver.findOne({ roomId });\n}\n\n/**\n * Get local room instance by roomId. (Can return \"undefined\" if the room is not available on this process)\n */\nexport function getLocalRoomById(roomId: string) {\n  return rooms[roomId];\n}\n\n/**\n * Disconnects every client on every room in the current process.\n */\nexport function disconnectAll(closeCode?: number) {\n  const promises: Array<Promise<any>> = [];\n\n  for (const roomId in rooms) {\n    if (!rooms.hasOwnProperty(roomId)) {\n      continue;\n    }\n\n    promises.push(rooms[roomId].disconnect(closeCode));\n  }\n\n  return promises;\n}\n\nasync function lockAndDisposeAll(): Promise<any> {\n  // remove processId from room count key\n  // (stops accepting new rooms on this process)\n  await stats.excludeProcess(processId);\n\n  // clear auto-persisting stats interval\n  if (enableHealthChecks) {\n    stats.clearAutoPersistInterval();\n  }\n\n  const noActiveRooms = new Deferred();\n  if (stats.local.roomCount <= 0) {\n    // no active rooms to dispose\n    noActiveRooms.resolve();\n\n  } else {\n    // wait for all rooms to be disposed\n    // TODO: set generous timeout in case\n    events.once('no-active-rooms', () => noActiveRooms.resolve());\n  }\n\n  // - lock all local rooms to prevent new joins\n  // - trigger `onBeforeShutdown()` on each room\n  for (const roomId in rooms) {\n    if (!rooms.hasOwnProperty(roomId)) {\n      continue;\n    }\n\n    const room = rooms[roomId];\n    room.lock();\n\n    if (isDevMode) {\n      // call default implementation of onBeforeShutdown() in dev mode\n      Room.prototype.onBeforeShutdown.call(room);\n\n    } else {\n      // call custom implementation of onBeforeShutdown() in production\n      room.onBeforeShutdown();\n    }\n  }\n\n  await noActiveRooms;\n}\n\nexport async function gracefullyShutdown(): Promise<any> {\n  if (state === MatchMakerState.SHUTTING_DOWN) {\n    return Promise.reject('already_shutting_down');\n  }\n\n  debugMatchMaking(`${processId} is shutting down!`);\n\n  state = MatchMakerState.SHUTTING_DOWN;\n\n  onReady = undefined;\n\n  if (isDevMode) {\n    // Reject pending allowReconnection() deferreds BEFORE caching.\n    // This should trigger a state cleanup via user's onLeave (e.g. players.delete)\n    // so the cached state doesn't contain stale player data from clients\n    for (const roomId in rooms) {\n      if (!rooms.hasOwnProperty(roomId)) { continue; }\n      rooms[roomId]['_rejectPendingReconnections']?.(\"devmode_restart\");\n    }\n\n    // Wait for async onLeave handlers to finish state cleanup.\n    await new Promise(resolve => setTimeout(resolve, 50));\n\n    await cacheRoomHistory(rooms);\n  }\n\n  // - lock existing rooms\n  // - stop accepting new rooms on this process\n  // - wait for all rooms to be disposed\n  await lockAndDisposeAll();\n\n  // make sure rooms are removed from cache\n  await removeRoomsByProcessId(processId);\n\n  // unsubscribe from process id channel\n  presence.unsubscribe(getProcessChannel());\n\n  // make sure all rooms are disposed\n  return Promise.all(disconnectAll(\n    (isDevMode)\n      ? CloseCode.MAY_TRY_RECONNECT\n      : CloseCode.SERVER_SHUTDOWN\n  ));\n}\n\n/**\n * DO NOT USE THIS IN PRODUCTION. \n * THIS METHOD IS MEANT TO BE USED FOR VITE DEV SERVER ONLY.\n * ---------------------------------------------------------\n *\n * \n * Lightweight HMR reload for dev mode. \n *\n * Unlike gracefullyShutdown() + setup() + accept(), this preserves the\n * matchMaker infrastructure (presence, driver, IPC subscriptions, processId)\n * and only cycles room instances: cache state \u2192 dispose \u2192 restore.\n */\nexport async function hotReload(): Promise<void> {\n  state = MatchMakerState.SHUTTING_DOWN;\n\n  // Reject pending allowReconnection() deferreds BEFORE caching.\n  // Triggers onLeave state cleanup so cached state is clean.\n  for (const roomId in rooms) {\n    if (!rooms.hasOwnProperty(roomId)) { continue; }\n    rooms[roomId]['_rejectPendingReconnections']?.(\"devmode_restart\");\n  }\n\n  // Wait for async onLeave handlers to finish state cleanup.\n  await new Promise(resolve => setTimeout(resolve, 50));\n\n  await cacheRoomHistory(rooms);\n\n  // Lock all rooms and trigger default onBeforeShutdown (dev mode impl).\n  const noActiveRooms = new Deferred();\n  if (stats.local.roomCount <= 0) {\n    noActiveRooms.resolve();\n  } else {\n    events.once('no-active-rooms', () => noActiveRooms.resolve());\n  }\n\n  for (const roomId in rooms) {\n    if (!rooms.hasOwnProperty(roomId)) { continue; }\n    const room = rooms[roomId];\n    room.lock();\n    Room.prototype.onBeforeShutdown.call(room);\n  }\n\n  await noActiveRooms;\n\n  // Disconnect all clients \u2014 they will auto-reconnect.\n  await Promise.all(disconnectAll(CloseCode.MAY_TRY_RECONNECT));\n\n  // Clear driver cache so reloadFromCache() can recreate rooms.\n  await removeRoomsByProcessId(processId);\n\n  // Restore rooms from cached state.\n  state = MatchMakerState.READY;\n  await reloadFromCache();\n  await stats.persist();\n}\n\n/**\n * Reserve a seat for a client in a room\n */\nexport async function reserveSeatFor(room: IRoomCache, options: ClientOptions, authData?: any) {\n  const sessionId: string = authData?.sessionId || generateId();\n\n  let successfulSeatReservation: boolean;\n\n  try {\n    successfulSeatReservation = await remoteRoomCall<Room>(\n      room.roomId,\n      '_reserveSeat' as keyof Room,\n      [sessionId, options, authData],\n      REMOTE_ROOM_SHORT_TIMEOUT,\n    );\n\n  } catch (e: any) {\n    debugMatchMaking(e);\n\n    //\n    // the room cache from an unavailable process might've been used here.\n    // (this is a broken state when a process wasn't gracefully shut down)\n    // perform a health-check on the process before proceeding.\n    //\n    if (\n      e.message === \"ipc_timeout\" &&\n      !(\n        enableHealthChecks &&\n        await healthCheckProcessId(room.processId)\n      )\n    ) {\n      throw new SeatReservationError(`process ${room.processId} is not available.`);\n\n    } else {\n      successfulSeatReservation = false;\n    }\n  }\n\n  if (!successfulSeatReservation) {\n    throw new SeatReservationError(`${room.roomId} is already full.`);\n  }\n\n  return buildSeatReservation(room, sessionId);\n}\n\n/**\n * Reserve multiple seats for clients in a room\n */\nexport async function reserveMultipleSeatsFor(room: IRoomCache, clientsData: Array<{ sessionId: string, options: ClientOptions, auth: any }>) {\n  let sessionIds: string[] = [];\n  let options: ClientOptions[] = [];\n  let authData: any[] = [];\n\n  for (const clientData of clientsData) {\n    sessionIds.push(clientData.sessionId);\n    options.push(clientData.options);\n    authData.push(clientData.auth);\n  }\n\n  debugMatchMaking(\n    'reserving multiple seats. sessionIds: \\'%s\\', roomId: \\'%s\\', processId: \\'%s\\'',\n    sessionIds.join(', '), room.roomId, processId,\n  );\n\n  let successfulSeatReservations: boolean[];\n\n  try {\n    successfulSeatReservations = await remoteRoomCall<Room>(\n      room.roomId,\n      '_reserveMultipleSeats' as keyof Room,\n      [sessionIds, options, authData],\n      REMOTE_ROOM_SHORT_TIMEOUT,\n    );\n\n  } catch (e: any) {\n    debugMatchMaking(e);\n\n    //\n    // the room cache from an unavailable process might've been used here.\n    // (this is a broken state when a process wasn't gracefully shut down)\n    // perform a health-check on the process before proceeding.\n    //\n    if (\n      e.message === \"ipc_timeout\" &&\n      !(\n        enableHealthChecks &&\n        await healthCheckProcessId(room.processId)\n      )\n    ) {\n      throw new SeatReservationError(`process ${room.processId} is not available.`);\n\n    } else {\n      throw new SeatReservationError(`${room.roomId} is already full.`);\n    }\n  }\n\n  return successfulSeatReservations;\n}\n\n/**\n * Build a seat reservation object.\n * @param room - The room to build a seat reservation for.\n * @param sessionId - The session ID of the client.\n * @returns A seat reservation object.\n */\nexport function buildSeatReservation(room: IRoomCache, sessionId: string) {\n  const seatReservation: ISeatReservation = {\n    name: room.name,\n    sessionId,\n    roomId: room.roomId,\n    processId: room.processId,\n  };\n\n  if (isDevMode) {\n    seatReservation.devMode = isDevMode;\n  }\n\n  if (room.publicAddress) {\n    seatReservation.publicAddress = room.publicAddress;\n  }\n\n  return seatReservation;\n}\n\nasync function callOnAuth(roomName: string, clientOptions?: ClientOptions, authContext?: AuthContext) {\n  const roomClass = getRoomClass(roomName);\n  if (roomClass && roomClass['onAuth'] && roomClass['onAuth'] !== Room['onAuth']) {\n    const result = await roomClass['onAuth'](authContext.token, clientOptions, authContext)\n    if (!result) {\n      throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n    }\n    return result;\n  }\n}\n\n/**\n * Perform health check on all processes\n */\nexport async function healthCheckAllProcesses() {\n  const allStats = await stats.fetchAll();\n  const activeProcessChannels = (await presence.channels(\"p:*\")).map(c => c.substring(2));\n\n  if (allStats.length > 0) {\n    await Promise.all(\n      allStats\n        .filter(stat => (\n          stat.processId !== processId && // skip current process\n          !activeProcessChannels.includes(stat.processId) // skip if channel is still listening\n        ))\n        .map(stat => healthCheckProcessId(stat.processId))\n    );\n  }\n}\n\n/**\n * Perform health check on a remote process\n * @param processId\n */\nconst _healthCheckByProcessId: { [processId: string]: Promise<any> } = {};\nexport function healthCheckProcessId(processId: string) {\n  //\n  // re-use the same promise if health-check is already in progress\n  // (may occur when _reserveSeat() fails multiple times for the same 'processId')\n  //\n  if (_healthCheckByProcessId[processId] !== undefined) {\n    return _healthCheckByProcessId[processId];\n  }\n\n  _healthCheckByProcessId[processId] = new Promise<boolean>(async (resolve, reject) => {\n    logger.debug(`> Performing health-check against processId: '${processId}'...`);\n\n    try {\n      const requestTime = Date.now();\n\n      await requestFromIPC<IRoomCache>(\n        presence,\n        getProcessChannel(processId),\n        'healthcheck',\n        [],\n        REMOTE_ROOM_SHORT_TIMEOUT,\n      );\n\n      logger.debug(`\u2705 Process '${processId}' successfully responded (${Date.now() - requestTime}ms)`);\n\n      // succeeded to respond\n      resolve(true)\n\n    } catch (e) {\n      // process failed to respond - remove it from stats\n      logger.debug(`\u274C Process '${processId}' failed to respond. Cleaning it up.`);\n      await stats.excludeProcess(processId);\n\n      // clean-up possibly stale room ids\n      if (!isDevMode) {\n        await removeRoomsByProcessId(processId);\n      }\n\n      resolve(false);\n    } finally {\n      delete _healthCheckByProcessId[processId];\n    }\n  });\n\n  return _healthCheckByProcessId[processId];\n}\n\n/**\n * Remove cached rooms by processId\n * @param processId\n */\nasync function removeRoomsByProcessId(processId: 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  await driver.cleanup(processId);\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      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\n/**\n * Used only during `joinOrCreate` to handle concurrent requests for creating a room.\n */\nasync function concurrentJoinOrCreateRoomLock(\n  handler: RegisteredHandler,\n  concurrencyKey: string,\n  callback: (roomId?: string) => Promise<IRoomCache>\n): Promise<IRoomCache> {\n  return new Promise(async (resolve, reject) => {\n    const hkey = getConcurrencyHashKey(handler.name);\n    const concurrency = await presence.hincrbyex(\n      hkey,\n      concurrencyKey,\n      1, // increment by 1\n      MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME * 2 // expire in 2x the time of MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME\n    ) - 1; // do not consider the current request\n\n    const fulfill = async (roomId?: string) => {\n      try {\n        resolve(await callback(roomId));\n\n      } catch (e) {\n        reject(e);\n\n      } finally {\n        await presence.hincrbyex(hkey, concurrencyKey, -1, MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME * 2);\n      }\n    };\n\n    if (concurrency > 0) {\n      debugMatchMaking(\n        'receiving %d concurrent joinOrCreate for \\'%s\\' (%s)',\n        concurrency, handler.name, concurrencyKey\n      );\n\n      try {\n        const roomId = await subscribeWithTimeout(\n          presence,\n          `concurrent:${handler.name}:${concurrencyKey}`,\n          (MAX_CONCURRENT_CREATE_ROOM_WAIT_TIME +\n            (Math.min(concurrency, 3) * 0.2)) * 1000 // convert to milliseconds\n        );\n\n        return await fulfill(roomId);\n      } catch (error) {\n        // Ignore ipc_timeout error\n      }\n    }\n\n    return await fulfill();\n  });\n}\n\nfunction onClientJoinRoom(room: Room, client: Client) {\n  // increment local CCU\n  stats.local.ccu++;\n  stats.persist();\n\n  handlers[room.roomName].emit('join', room, client);\n}\n\nfunction onClientLeaveRoom(room: Room, client: Client, willDispose: boolean) {\n  // decrement local CCU\n  stats.local.ccu--;\n  stats.persist();\n\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\nfunction onVisibilityChange(room: Room, isInvisible: boolean): void {\n  handlers[room.roomName].emit('visibility-change', room, isInvisible);\n}\n\nfunction onMetadataChange(room: Room): void {\n  handlers[room.roomName].emit('metadata-change', room);\n}\n\nasync function disposeRoom(roomName: string, room: Room) {\n  debugMatchMaking('disposing \\'%s\\' (%s) on processId \\'%s\\' (graceful shutdown: %s)', roomName, room.roomId, processId, state === MatchMakerState.SHUTTING_DOWN);\n\n  //\n  // FIXME: this call should not be necessary.\n  //\n  // there's an unidentified edge case using LocalDriver where Room._dispose()\n  // doesn't seem to be called [?], but \"disposeRoom\" is, leaving the matchmaker\n  // in a broken state. (repeated ipc_timeout's for seat reservation on\n  // non-existing rooms)\n  //\n  driver.remove(room['_listing'].roomId);\n  stats.local.roomCount--;\n\n  // decrease amount of rooms this process is handling\n  if (state !== MatchMakerState.SHUTTING_DOWN) {\n    stats.persist();\n\n    // remove from devMode restore list\n    if (isDevMode) {\n      await presence.hdel(getRoomRestoreListKey(), room.roomId);\n    }\n  }\n\n  // emit disposal on registered session handler\n  handlers[roomName].emit('dispose', room);\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//\nfunction getRoomChannel(roomId: string) {\n  return `$${roomId}`;\n}\n\nfunction getConcurrencyHashKey(roomName: string) {\n  // concurrency hash\n  return `ch:${roomName}`;\n}\n\nfunction getProcessChannel(id: string = processId) {\n  return `p:${id}`;\n}\n"],
  "mappings": "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",
  "names": ["processId"]
}
