From 7181912607cd41a6fd757bb32b0c2d98548ca078 Mon Sep 17 00:00:00 2001 From: Nour Alharithi Date: Wed, 25 Oct 2023 14:27:16 -0700 Subject: [PATCH] have redis working --- dump.rdb | Bin 0 -> 88 bytes example/newClient.ts | 0 package.json | 5 + src/dlob-subscriber/DLOBSubscriberIO.ts | 14 +- src/index.ts | 27 +++- src/utils/redisClient.ts | 124 ++++++++++++++++++ src/utils/utils.ts | 13 +- src/wsConnectionManager.ts | 49 +++++++ yarn.lock | 163 +++++++++++++++++++++++- 9 files changed, 384 insertions(+), 11 deletions(-) create mode 100644 dump.rdb create mode 100644 example/newClient.ts create mode 100644 src/utils/redisClient.ts create mode 100644 src/wsConnectionManager.ts diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000000000000000000000000000000000000..9c1c3154358e54599d7201eae61a0182d0600a19 GIT binary patch literal 88 zcmWG?b@2=~FfcUy#aWb^l3A=>; io: Server; + redisClient: RedisClient; - constructor(config: DLOBSubscriptionConfig) { + constructor(config: DLOBSubscriptionConfig & { redisClient: RedisClient }) { super(config); + this.redisClient = config.redisClient; // Set up appropriate maps this.lastSeenL2Formatted = new Map(); @@ -43,7 +46,7 @@ export class DLOBSubscriberIO extends DLOBSubscriber { marketIndex: market.marketIndex, marketType: MarketType.PERP, marketName: market.symbol, - depth: 2, + depth: -1, includeVamm: true, numVammOrders: 100, updateOnChange: true, @@ -55,7 +58,7 @@ export class DLOBSubscriberIO extends DLOBSubscriber { marketIndex: market.marketIndex, marketType: MarketType.SPOT, marketName: market.symbol, - depth: 2, + depth: -1, includeVamm: false, updateOnChange: true, fallbackL2Generators: [], @@ -101,6 +104,9 @@ export class DLOBSubscriberIO extends DLOBSubscriber { l2Args.marketType, l2Args.marketIndex ); - this.io.emit('l2Update', l2Formatted); + this.redisClient.client.publish( + l2Args.marketName, + JSON.stringify(l2Formatted) + ); } } diff --git a/src/index.ts b/src/index.ts index 66d5216..f0f132c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ import { import { DLOBSubscriberIO } from './dlob-subscriber/DLOBSubscriberIO'; import { handleResponseTime } from './core/middleware'; import { handleHealthCheck } from './core/metrics'; +import { RedisClient } from './utils/redisClient'; require('dotenv').config(); const driftEnv = (process.env.ENV || 'devnet') as DriftEnv; @@ -130,13 +131,21 @@ const initializeAllMarketSubscribers = async (driftClient: DriftClient) => { }; if (market.phoenixMarket) { - const phoenixSubscriber = getPhoenixSubscriber(driftClient, market); + const phoenixSubscriber = getPhoenixSubscriber( + driftClient, + market, + sdkConfig + ); await phoenixSubscriber.subscribe(); markets[market.marketIndex].phoenix = phoenixSubscriber; } if (market.serumMarket) { - const serumSubscriber = getSerumSubscriber(driftClient, market); + const serumSubscriber = getSerumSubscriber( + driftClient, + market, + sdkConfig + ); await serumSubscriber.subscribe(); markets[market.marketIndex].serum = serumSubscriber; } @@ -195,11 +204,15 @@ const main = async () => { ); await userStatsMap.subscribe(); + const redisClient = new RedisClient('localhost', '6379'); + await redisClient.connect(); + const dlobSubscriber = new DLOBSubscriberIO({ driftClient, dlobSource: userMap, slotSource: slotSubscriber, updateFrequency: ORDERBOOK_UPDATE_INTERVAL, + redisClient, }); await dlobSubscriber.subscribe(); @@ -385,6 +398,8 @@ const main = async () => { try { const { marketName, marketIndex, marketType } = req.query; const { normedMarketType, normedMarketIndex, error } = validateDlobQuery( + driftClient, + driftEnv, marketType as string, marketIndex as string, marketName as string @@ -454,6 +469,8 @@ const main = async () => { } = req.query; const { normedMarketType, normedMarketIndex, error } = validateDlobQuery( + driftClient, + driftEnv, marketType as string, marketIndex as string, marketName as string @@ -561,6 +578,8 @@ const main = async () => { } = req.query; const { normedMarketType, normedMarketIndex, error } = validateDlobQuery( + driftClient, + driftEnv, marketType as string, marketIndex as string, marketName as string @@ -674,6 +693,8 @@ const main = async () => { const l2s = normedParams.map((normedParam) => { const { normedMarketType, normedMarketIndex, error } = validateDlobQuery( + driftClient, + driftEnv, normedParam['marketType'] as string, normedParam['marketIndex'] as string, normedParam['marketName'] as string @@ -760,6 +781,8 @@ const main = async () => { const { marketName, marketIndex, marketType, includeOracle } = req.query; const { normedMarketType, normedMarketIndex, error } = validateDlobQuery( + driftClient, + driftEnv, marketType as string, marketIndex as string, marketName as string diff --git a/src/utils/redisClient.ts b/src/utils/redisClient.ts new file mode 100644 index 0000000..1bdf392 --- /dev/null +++ b/src/utils/redisClient.ts @@ -0,0 +1,124 @@ +import Redis, { RedisOptions } from 'ioredis'; +import { sleep } from './utils'; + +export const getRedisClient = ( + host?: string, + port?: string, + password?: string, + db?: number, + opts?: RedisOptions +): Redis => { + if (host && port) { + console.log(`Connecting to configured redis:: ${host}:${port}`); + + const redisClient = new Redis({ + host: host, + port: parseInt(port, 10), + password: password, + ...(opts ?? {}), + retryStrategy: (times) => { + const delay = Math.min(times * 1000, 10000); + console.log( + `Reconnecting to Redis in ${delay}ms... (retries: ${times})` + ); + return delay; + }, + reconnectOnError: (err) => { + const targetError = 'ECONNREFUSED'; + if (err.message.includes(targetError)) { + console.log( + `Redis error: ${targetError}. Attempting to reconnect...` + ); + return true; + } + return false; + }, + maxRetriesPerRequest: null, // unlimited retries + }); + + redisClient.on('connect', () => { + console.log('Connected to Redis.'); + }); + + redisClient.on('error', (err) => { + console.error('Redis error:', err); + }); + + redisClient.on('reconnecting', () => { + console.log('Reconnecting to Redis...'); + }); + + return redisClient; + } + + console.log(`Using default redis`); + return new Redis({ db }); +}; + +/** + * Wrapper around the redis client. + * + * You can hover over the underlying redis client methods for explanations of the methods, but will also include links to DOCS for some important concepts below: + * + * zRange, zRangeByScore etc.: + * - All of the "z" methods are methods that use sorted sets. + * - Sorted sets are explained here : https://redis.io/docs/data-types/sorted-sets/ + */ +export class RedisClient { + public client: Redis; + + connectionPromise: Promise; + + constructor( + host?: string, + port?: string, + password?: string, + db?: number, + opts?: RedisOptions + ) { + this.client = getRedisClient(host, port, password, db, opts); + } + + /** + * Should avoid using this unless necessary. + * @returns + */ + public forceGetClient() { + return this.client; + } + + public get connected() { + return this?.client?.status === 'ready'; + } + + async connect() { + if (this.client.status === 'ready' || this.client.status === 'connect') { + return; + } + + if (this.client.status === 'connecting') { + await sleep(100); + return this.connect(); // recursive call to check again + } + + try { + await this.client.connect(); + } catch (e) { + console.error(e); + } + } + + disconnect() { + this.client.disconnect(); + } + + private assertConnected() { + if (!this.connected) { + throw 'Redis client not connected'; + } + } + + private getPrefixForMetrics(key: string) { + return key.split(':')?.[0]; + } +} diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 37e7936..848de31 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,6 @@ import { DriftClient, + DriftEnv, L2OrderBook, MarketType, PerpMarkets, @@ -12,7 +13,6 @@ import { } from '@drift-labs/sdk'; import { logger } from './logger'; import { NextFunction, Request, Response } from 'express'; -import { driftClient, driftEnv, sdkConfig } from '..'; export const l2WithBNToStrings = (l2: L2OrderBook): any => { for (const key of Object.keys(l2)) { @@ -111,7 +111,8 @@ export const normalizeBatchQueryParams = (rawParams: { }; export const validateWsSubscribeMsg = ( - msg: any + msg: any, + sdkConfig: any ): { valid: boolean; msg?: string } => { const maxPerpMarketIndex = Math.max( ...sdkConfig.PERP_MARKETS.map((m) => m.marketIndex) @@ -158,6 +159,8 @@ export const validateWsSubscribeMsg = ( }; export const validateDlobQuery = ( + driftClient: DriftClient, + driftEnv: DriftEnv, marketType?: string, marketIndex?: string, marketName?: string @@ -248,7 +251,8 @@ export function errorHandler( export const getPhoenixSubscriber = ( driftClient: DriftClient, - marketConfig: SpotMarketConfig + marketConfig: SpotMarketConfig, + sdkConfig ): PhoenixSubscriber => { return new PhoenixSubscriber({ connection: driftClient.connection, @@ -262,7 +266,8 @@ export const getPhoenixSubscriber = ( export const getSerumSubscriber = ( driftClient: DriftClient, - marketConfig: SpotMarketConfig + marketConfig: SpotMarketConfig, + sdkConfig ): SerumSubscriber => { return new SerumSubscriber({ connection: driftClient.connection, diff --git a/src/wsConnectionManager.ts b/src/wsConnectionManager.ts new file mode 100644 index 0000000..9734f80 --- /dev/null +++ b/src/wsConnectionManager.ts @@ -0,0 +1,49 @@ +import cors from 'cors'; +import express from 'express'; +import * as http from 'http'; +import { Server } from 'socket.io'; +import compression from 'compression'; +import { sleep } from './utils/utils'; +import { RedisClient } from './utils/redisClient'; + +const app = express(); +app.use(cors({ origin: '*' })); +app.use(compression()); +app.set('trust proxy', 1); + +const server = http.createServer(app); +const io = new Server(server); + +async function main() { + const redisClient = new RedisClient('localhost', '6379'); + await redisClient.connect(); + + io.on('connection', (socket) => { + socket.on('subscribe', (channel) => { + console.log('Subscribing to channel', channel); + redisClient.client.subscribe(channel); + redisClient.client.on('message', (subscribedChannel, message) => { + console.log(message); + if (subscribedChannel === channel) { + socket.emit(channel, JSON.parse(message)); + } + }); + }); + }); + + server.listen('3000', () => { + console.log('connection manager running on 3000'); + }); +} + +async function recursiveTryCatch(f: () => void) { + try { + await f(); + } catch (e) { + console.error(e); + await sleep(15000); + await recursiveTryCatch(f); + } +} + +recursiveTryCatch(() => main()); diff --git a/yarn.lock b/yarn.lock index 2195452..820677a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -220,6 +220,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@ioredis/commands@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== + "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" @@ -884,6 +889,40 @@ assert "^2.0.0" buffer "^6.0.1" +"@redis/bloom@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.2.0.tgz#d3fd6d3c0af3ef92f26767b56414a370c7b63b71" + integrity sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg== + +"@redis/client@1.5.11": + version "1.5.11" + resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.5.11.tgz#5ee8620fea56c67cb427228c35d8403518efe622" + integrity sha512-cV7yHcOAtNQ5x/yQl7Yw1xf53kO0FNDTdDU6bFIMbW6ljB7U7ns0YRM+QIkpoqTAt6zK5k9Fq0QWlUbLcq9AvA== + dependencies: + cluster-key-slot "1.1.2" + generic-pool "3.9.0" + yallist "4.0.0" + +"@redis/graph@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.1.0.tgz#cc2b82e5141a29ada2cce7d267a6b74baa6dd519" + integrity sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg== + +"@redis/json@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.6.tgz#b7a7725bbb907765d84c99d55eac3fcf772e180e" + integrity sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw== + +"@redis/search@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.5.tgz#682b68114049ff28fdf2d82c580044dfb74199fe" + integrity sha512-hPP8w7GfGsbtYEJdn4n7nXa6xt6hVZnnDktKW4ArMaFQ/m/aR7eFvsLQmG/mn1Upq99btPJk+F27IQ2dYpCoUg== + +"@redis/time-series@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.5.tgz#a6d70ef7a0e71e083ea09b967df0a0ed742bc6ad" + integrity sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg== + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -1356,6 +1395,13 @@ dependencies: "@types/node" "*" +"@types/redis@^4.0.11": + version "4.0.11" + resolved "https://registry.yarnpkg.com/@types/redis/-/redis-4.0.11.tgz#0bb4c11ac9900a21ad40d2a6768ec6aaf651c0e1" + integrity sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg== + dependencies: + redis "*" + "@types/restify@4.3.8": version "4.3.8" resolved "https://registry.yarnpkg.com/@types/restify/-/restify-4.3.8.tgz#1e504995ef770a7149271e2cd639767cc7925245" @@ -1829,6 +1875,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +cluster-key-slot@1.1.2, cluster-key-slot@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2015,6 +2066,16 @@ delay@^5.0.0: resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== +denque@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" + integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== + +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== + depd@2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -2568,6 +2629,11 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== +generic-pool@3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" + integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" @@ -2734,6 +2800,21 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ioredis@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" + integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== + dependencies: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -2928,6 +3009,16 @@ light-my-request@^4.2.0: process-warning "^1.0.0" set-cookie-parser "^2.4.1" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== + lodash.merge@4.6.2, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -3093,6 +3184,11 @@ node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== +notepack.io@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/notepack.io/-/notepack.io-2.2.0.tgz#d7ea71d1cb90094f88c6f3c8d84277c2d0cd101c" + integrity sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw== + object-assign@^4: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -3395,6 +3491,45 @@ real-require@^0.1.0: resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== +redis-commands@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" + integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== + +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== + dependencies: + redis-errors "^1.0.0" + +redis@*, redis@^4.6.10: + version "4.6.10" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.6.10.tgz#07f6ea2b2c5455b098e76d1e8c9b3376114e9458" + integrity sha512-mmbyhuKgDiJ5TWUhiKhBssz+mjsuSI/lSZNPI9QvZOYzWvYGejtb+W3RlDDf8LD6Bdl5/mZeG8O1feUGhXTxEg== + dependencies: + "@redis/bloom" "1.2.0" + "@redis/client" "1.5.11" + "@redis/graph" "1.1.0" + "@redis/json" "1.0.6" + "@redis/search" "1.1.5" + "@redis/time-series" "1.0.5" + +redis@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/redis/-/redis-3.1.2.tgz#766851117e80653d23e0ed536254677ab647638c" + integrity sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw== + dependencies: + denque "^1.5.0" + redis-commands "^1.7.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + regenerator-runtime@^0.13.11: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" @@ -3641,6 +3776,11 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +socket.io-adapter@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.2.0.tgz#43af9157c4609e74b8addc6867873ac7eb48fda2" + integrity sha512-rG49L+FwaVEwuAdeBRq49M97YI3ElVabJPzvHT9S6a2CWhDKnjSFasvwAwSYPRhQzfn4NtDIbCaGYgOCOU/rlg== + socket.io-adapter@~2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" @@ -3666,6 +3806,17 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" +socket.io-redis@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socket.io-redis/-/socket.io-redis-6.1.1.tgz#2361029a6c0b25c602d1422e1beb41907fd0e8bf" + integrity sha512-jeaXe3TGKC20GMSlPHEdwTUIWUpay/L7m5+S9TQcOf22p9Llx44/RkpJV08+buXTZ8E+aivOotj2RdeFJJWJJQ== + dependencies: + debug "~4.3.1" + notepack.io "~2.2.0" + redis "^3.0.0" + socket.io-adapter "~2.2.0" + uid2 "0.0.3" + socket.io@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" @@ -3717,6 +3868,11 @@ stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -3930,6 +4086,11 @@ typescript@4.5.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== +uid2@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + integrity sha512-5gSP1liv10Gjp8cMEnFd6shzkL/D6W1uhXSFNCxDC+YI8+L8wkCYCbJ7n77Ezb4wE/xzMogecE+DtamEe9PZjg== + undici-types@~5.25.1: version "5.25.3" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" @@ -4083,7 +4244,7 @@ xtend@^4.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -yallist@^4.0.0: +yallist@4.0.0, yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==