UNPKG

@colyseus/redis-driver

Version:

<div align="center"> <a href="https://github.com/colyseus/colyseus"> <img src="media/logo.svg?raw=true" width="60%" height="300" /> </a> <br> <br> <a href="https://npmjs.com/package/colyseus"> <img src="https://img.shields.io/npm/dm/coly

118 lines (117 loc) 3.86 kB
// packages/drivers/redis-driver/src/RedisDriver.ts import { Redis, Cluster } from "ioredis"; import { debugMatchMaking, initializeRoomCache } from "@colyseus/core"; import { Query } from "./Query.mjs"; var ROOMCACHES_KEY = "roomcaches"; var RedisDriver = class { constructor(options, clusterOptions) { this._roomCacheRequestByName = {}; this._client = options instanceof Redis || options instanceof Cluster ? options : Array.isArray(options) ? new Cluster(options, clusterOptions) : new Redis(options); } async has(roomId) { return await this._client.hexists(ROOMCACHES_KEY, roomId) === 1; } async query(conditions, sortOptions) { const query = new Query(this.getRooms(), conditions); if (sortOptions) { query.sort(sortOptions); } return query.all(); } async cleanup(processId) { const cachedRooms = await this.query({ processId }); debugMatchMaking("removing stale rooms by processId %s (%s rooms found)", processId, cachedRooms.length); const itemsPerCommand = 500; for (let i = 0; i < cachedRooms.length; i += itemsPerCommand) { await this._client.hdel(ROOMCACHES_KEY, ...cachedRooms.slice(i, i + itemsPerCommand).map((room) => room.roomId)); } } findOne(conditions, sortOptions) { if (typeof conditions.roomId !== "undefined") { return new Promise((resolve, reject) => { this._client.hget(ROOMCACHES_KEY, conditions.roomId).then((roomcache) => { if (roomcache) { resolve(initializeRoomCache(JSON.parse(roomcache))); } else { resolve(void 0); } }).catch(reject); }); } else { const query = new Query(this.getRooms(conditions["name"]), conditions); if (sortOptions) { query.sort(sortOptions); } return query; } } getRooms(roomName) { if (this._roomCacheRequestByName[roomName] !== void 0) { return this._roomCacheRequestByName[roomName]; } const roomCacheRequest = this._concurrentRoomCacheRequest || this._client.hgetall(ROOMCACHES_KEY); this._concurrentRoomCacheRequest = roomCacheRequest; this._roomCacheRequestByName[roomName] = roomCacheRequest.then((result) => { this._concurrentRoomCacheRequest = void 0; delete this._roomCacheRequestByName[roomName]; let roomcaches = Object.entries(result ?? {}); if (roomName !== void 0) { const roomNameField = `"name":"${roomName}"`; roomcaches = roomcaches.filter(([, roomcache]) => roomcache.includes(roomNameField)); } return roomcaches.map( ([, roomcache]) => initializeRoomCache(JSON.parse(roomcache)) ); }); return this._roomCacheRequestByName[roomName]; } async update(room, operations) { if (operations.$set) { for (const field in operations.$set) { if (operations.$set.hasOwnProperty(field)) { room[field] = operations.$set[field]; } } } if (operations.$inc) { for (const field in operations.$inc) { if (operations.$inc.hasOwnProperty(field)) { room[field] += operations.$inc[field]; } } } await this._client.hset(ROOMCACHES_KEY, room.roomId, JSON.stringify(room)); return true; } async persist(room, _ = false) { if (!room.roomId) { debugMatchMaking("RedisDriver: can't .persist() without a `roomId`"); return false; } await this._client.hset(ROOMCACHES_KEY, room.roomId, JSON.stringify(room)); return true; } async remove(roomId) { const result = await this._client.hdel(ROOMCACHES_KEY, roomId); return result > 0; } async shutdown() { await this._client.quit(); } // // only relevant for the test-suite. // not used during runtime. // clear() { this._client.del(ROOMCACHES_KEY); } }; export { RedisDriver };