diff --git a/src/middleware/queryCacher.ts b/src/middleware/queryCacher.ts new file mode 100644 index 0000000..e1f9f09 --- /dev/null +++ b/src/middleware/queryCacher.ts @@ -0,0 +1,35 @@ +import redis from "../utils/redis"; +import { Logger } from "../utils/logger"; +import { skipSegmentsHashKey, skipSegmentsKey } from "./redisKeys"; +import { Service, VideoID, VideoIDHash } from "../types/segments.model"; + +async function get(fetchFromDB: () => Promise, key: string): Promise { + const {err, reply} = await redis.getAsync(key); + + if (!err && reply) { + try { + Logger.debug("Got data from redis: " + reply); + return JSON.parse(reply); + } catch (e) { + // If all else, continue on to fetching from the database + } + } + + const data = await fetchFromDB(); + + redis.setAsync(key, JSON.stringify(data)); + return data; +} + +function clearVideoCache(videoInfo: { videoID: VideoID; hashedVideoID: VideoIDHash; service: Service; }) { + if (videoInfo) { + redis.delAsync(skipSegmentsKey(videoInfo.videoID, videoInfo.service)); + redis.delAsync(skipSegmentsHashKey(videoInfo.hashedVideoID, videoInfo.service)); + } +} + + +export const QueryCacher = { + get, + clearVideoCache +} \ No newline at end of file diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index c3e7cbf..63ad30e 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import { RedisClient } from 'redis'; import { config } from '../config'; import { db, privateDB } from '../databases/databases'; import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys'; @@ -9,8 +8,7 @@ import { getCategoryActionType } from '../utils/categoryInfo'; import { getHash } from '../utils/getHash'; import { getIP } from '../utils/getIP'; import { Logger } from '../utils/logger'; -import redis from '../utils/redis'; -import { getSkipSegmentsByHash } from './getSkipSegmentsByHash'; +import { QueryCacher } from '../middleware/queryCacher' async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { @@ -133,10 +131,10 @@ async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service `SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden", "hashedVideoID" FROM "sponsorTimes" WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, [hashedVideoIDPrefix + '%', service] - ); + ) as Promise; if (hashedVideoIDPrefix.length === 4) { - return await getSegmentsFromDB(fetchFromDB, skipSegmentsHashKey(hashedVideoIDPrefix, service)) + return await QueryCacher.get(fetchFromDB, skipSegmentsHashKey(hashedVideoIDPrefix, service)) } return await fetchFromDB(); @@ -149,27 +147,9 @@ async function getSegmentsFromDBByVideoID(videoID: VideoID, service: Service): P `SELECT "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden" FROM "sponsorTimes" WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, [videoID, service] - ); + ) as Promise; - return await getSegmentsFromDB(fetchFromDB, skipSegmentsKey(videoID, service)) -} - -async function getSegmentsFromDB(fetchFromDB: () => Promise, key: string): Promise { - const {err, reply} = await redis.getAsync(key); - - if (!err && reply) { - try { - Logger.debug("Got data from redis: " + reply); - return JSON.parse(reply); - } catch (e) { - // If all else, continue on to fetching from the database - } - } - - const data = await fetchFromDB(); - - redis.setAsync(key, JSON.stringify(data)); - return data; + return await QueryCacher.get(fetchFromDB, skipSegmentsKey(videoID, service)) } //gets a weighted random choice from the choices array based on their `votes` property. diff --git a/src/routes/postSkipSegments.ts b/src/routes/postSkipSegments.ts index 72468b3..2806e8a 100644 --- a/src/routes/postSkipSegments.ts +++ b/src/routes/postSkipSegments.ts @@ -16,6 +16,7 @@ import redis from '../utils/redis'; import { Category, CategoryActionType, IncomingSegment, Segment, SegmentUUID, Service, VideoDuration, VideoID } from '../types/segments.model'; import { deleteLockCategories } from './deleteLockCategories'; import { getCategoryActionType } from '../utils/categoryInfo'; +import { QueryCacher } from '../middleware/queryCacher'; interface APIVideoInfo { err: string | boolean, @@ -528,8 +529,11 @@ export async function postSkipSegments(req: Request, res: Response) { await privateDB.prepare('run', `INSERT INTO "sponsorTimes" VALUES(?, ?, ?)`, [videoID, hashedIP, timeSubmitted]); // Clear redis cache for this video - redis.delAsync(skipSegmentsKey(videoID, service)); - redis.delAsync(skipSegmentsHashKey(hashedVideoID, service)); + QueryCacher.clearVideoCache({ + videoID, + hashedVideoID, + service + }); } catch (err) { //a DB change probably occurred res.sendStatus(500); diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index 0bc686c..0e3c02a 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -15,6 +15,7 @@ import redis from '../utils/redis'; import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys'; import { Category, CategoryActionType, HashedIP, IPAddress, SegmentUUID, Service, VideoID, VideoIDHash } from '../types/segments.model'; import { getCategoryActionType } from '../utils/categoryInfo'; +import { QueryCacher } from '../middleware/queryCacher'; const voteTypes = { normal: 0, @@ -230,7 +231,7 @@ async function categoryVote(UUID: SegmentUUID, userID: UserID, isVIP: boolean, i } } - clearRedisCache(videoInfo); + QueryCacher.clearVideoCache(videoInfo); res.sendStatus(finalResponse.finalStatus); } @@ -416,7 +417,7 @@ export async function voteOnSponsorTime(req: Request, res: Response) { await db.prepare('run', 'UPDATE "sponsorTimes" SET locked = 0 WHERE "UUID" = ?', [UUID]); } - clearRedisCache(videoInfo); + QueryCacher.clearVideoCache(videoInfo); //for each positive vote, see if a hidden submission can be shown again if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) { @@ -465,11 +466,4 @@ export async function voteOnSponsorTime(req: Request, res: Response) { res.status(500).json({error: 'Internal error creating segment vote'}); } -} - -function clearRedisCache(videoInfo: { videoID: VideoID; hashedVideoID: VideoIDHash; service: Service; }) { - if (videoInfo) { - redis.delAsync(skipSegmentsKey(videoInfo.videoID, videoInfo.service)); - redis.delAsync(skipSegmentsHashKey(videoInfo.hashedVideoID, videoInfo.service)); - } -} +} \ No newline at end of file