From f86cdc393336932fb6b46dff3aaafbb9ea740a00 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 5 Oct 2023 11:32:37 -0500 Subject: [PATCH] self clearing gsihandler caches when user is inactive --- packages/dota/src/dota/GSIServer.ts | 19 +++++++++++++++++++ packages/dota/src/dota/clearCacheForUser.ts | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/dota/src/dota/GSIServer.ts b/packages/dota/src/dota/GSIServer.ts index 42a8b08a..0f531026 100644 --- a/packages/dota/src/dota/GSIServer.ts +++ b/packages/dota/src/dota/GSIServer.ts @@ -8,6 +8,7 @@ import { newData, processChanges } from './globalEventEmitter.js' import { emitMinimapBlockerStatus } from './GSIHandler.js' import { gsiHandlers } from './lib/consts.js' import { validateToken } from './validateToken.js' +import { checkForInactiveTokens, tokenLastPostTimestamps } from './clearCacheForUser.js' function handleSocketAuth(socket: Socket, next: (err?: Error) => void) { const { token } = socket.handshake.auth @@ -63,6 +64,21 @@ class GSIServer { app.use(express.urlencoded({ extended: true, limit: '1mb' })) app.post('/', validateToken, processChanges('previously'), processChanges('added'), newData) + app.post( + '/', + validateToken, + (req: Request, res: Response, next: () => void) => { + const token = req.body.auth.token as string + + // Update the timestamp for this token + tokenLastPostTimestamps.set(token, Date.now()) + + next() + }, + processChanges('previously'), + processChanges('added'), + newData, + ) app.get('/', (req: Request, res: Response) => { res.status(200).json({ status: 'ok' }) @@ -74,6 +90,9 @@ class GSIServer { this.io.use(handleSocketAuth) this.io.on('connection', handleSocketConnection) + + // Set up the repeating timer + setInterval(checkForInactiveTokens, 60 * 1000) // Run every minute } init() { diff --git a/packages/dota/src/dota/clearCacheForUser.ts b/packages/dota/src/dota/clearCacheForUser.ts index a65015c7..bfe0028c 100644 --- a/packages/dota/src/dota/clearCacheForUser.ts +++ b/packages/dota/src/dota/clearCacheForUser.ts @@ -1,10 +1,25 @@ import { getAuthProvider } from '../twitch/lib/getAuthProvider.js' import { SocketClient } from '../types.js' +import { logger } from '../utils/logger.js' import { deleteRedisData } from './GSIHandler.js' import { gsiHandlers, twitchIdToToken } from './lib/consts.js' -// three types of in-memory cache exists +// This will hold the last POST request timestamp for each token +export const tokenLastPostTimestamps: Map = new Map() + +// Function to check for inactive tokens and delete the corresponding gsiHandler +export async function checkForInactiveTokens() { + const now = Date.now() + const timeoutMillis = 60 * 1000 // 1 minute + for (const [token, timestamp] of tokenLastPostTimestamps.entries()) { + if (now - timestamp > timeoutMillis) { + await clearCacheForUser(gsiHandlers.get(token)?.client) + } + } +} + +// three types of in-memory cache exists export async function clearCacheForUser(client?: SocketClient | null) { if (!client) return false @@ -24,5 +39,7 @@ export async function clearCacheForUser(client?: SocketClient | null) { await deleteRedisData(client) gsiHandlers.delete(client.token) + + tokenLastPostTimestamps.delete(client.token) return true }