@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
JavaScript
// 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
};