mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-11 05:57:04 +03:00
Move redis code to middleware
This commit is contained in:
35
src/middleware/queryCacher.ts
Normal file
35
src/middleware/queryCacher.ts
Normal file
@@ -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<T>(fetchFromDB: () => Promise<T[]>, key: string): Promise<T[]> {
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { RedisClient } from 'redis';
|
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
import { db, privateDB } from '../databases/databases';
|
import { db, privateDB } from '../databases/databases';
|
||||||
import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys';
|
import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys';
|
||||||
@@ -9,8 +8,7 @@ import { getCategoryActionType } from '../utils/categoryInfo';
|
|||||||
import { getHash } from '../utils/getHash';
|
import { getHash } from '../utils/getHash';
|
||||||
import { getIP } from '../utils/getIP';
|
import { getIP } from '../utils/getIP';
|
||||||
import { Logger } from '../utils/logger';
|
import { Logger } from '../utils/logger';
|
||||||
import redis from '../utils/redis';
|
import { QueryCacher } from '../middleware/queryCacher'
|
||||||
import { getSkipSegmentsByHash } from './getSkipSegmentsByHash';
|
|
||||||
|
|
||||||
|
|
||||||
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
|
async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
|
||||||
@@ -133,10 +131,10 @@ async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service
|
|||||||
`SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden", "hashedVideoID" FROM "sponsorTimes"
|
`SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden", "hashedVideoID" FROM "sponsorTimes"
|
||||||
WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
||||||
[hashedVideoIDPrefix + '%', service]
|
[hashedVideoIDPrefix + '%', service]
|
||||||
);
|
) as Promise<DBSegment[]>;
|
||||||
|
|
||||||
if (hashedVideoIDPrefix.length === 4) {
|
if (hashedVideoIDPrefix.length === 4) {
|
||||||
return await getSegmentsFromDB(fetchFromDB, skipSegmentsHashKey(hashedVideoIDPrefix, service))
|
return await QueryCacher.get(fetchFromDB, skipSegmentsHashKey(hashedVideoIDPrefix, service))
|
||||||
}
|
}
|
||||||
|
|
||||||
return await fetchFromDB();
|
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"
|
`SELECT "startTime", "endTime", "votes", "locked", "UUID", "category", "videoDuration", "shadowHidden" FROM "sponsorTimes"
|
||||||
WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
||||||
[videoID, service]
|
[videoID, service]
|
||||||
);
|
) as Promise<DBSegment[]>;
|
||||||
|
|
||||||
return await getSegmentsFromDB(fetchFromDB, skipSegmentsKey(videoID, service))
|
return await QueryCacher.get(fetchFromDB, skipSegmentsKey(videoID, service))
|
||||||
}
|
|
||||||
|
|
||||||
async function getSegmentsFromDB(fetchFromDB: () => Promise<DBSegment[]>, key: string): Promise<DBSegment[]> {
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//gets a weighted random choice from the choices array based on their `votes` property.
|
//gets a weighted random choice from the choices array based on their `votes` property.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import redis from '../utils/redis';
|
|||||||
import { Category, CategoryActionType, IncomingSegment, Segment, SegmentUUID, Service, VideoDuration, VideoID } from '../types/segments.model';
|
import { Category, CategoryActionType, IncomingSegment, Segment, SegmentUUID, Service, VideoDuration, VideoID } from '../types/segments.model';
|
||||||
import { deleteLockCategories } from './deleteLockCategories';
|
import { deleteLockCategories } from './deleteLockCategories';
|
||||||
import { getCategoryActionType } from '../utils/categoryInfo';
|
import { getCategoryActionType } from '../utils/categoryInfo';
|
||||||
|
import { QueryCacher } from '../middleware/queryCacher';
|
||||||
|
|
||||||
interface APIVideoInfo {
|
interface APIVideoInfo {
|
||||||
err: string | boolean,
|
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]);
|
await privateDB.prepare('run', `INSERT INTO "sponsorTimes" VALUES(?, ?, ?)`, [videoID, hashedIP, timeSubmitted]);
|
||||||
|
|
||||||
// Clear redis cache for this video
|
// Clear redis cache for this video
|
||||||
redis.delAsync(skipSegmentsKey(videoID, service));
|
QueryCacher.clearVideoCache({
|
||||||
redis.delAsync(skipSegmentsHashKey(hashedVideoID, service));
|
videoID,
|
||||||
|
hashedVideoID,
|
||||||
|
service
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
//a DB change probably occurred
|
//a DB change probably occurred
|
||||||
res.sendStatus(500);
|
res.sendStatus(500);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import redis from '../utils/redis';
|
|||||||
import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys';
|
import { skipSegmentsHashKey, skipSegmentsKey } from '../middleware/redisKeys';
|
||||||
import { Category, CategoryActionType, HashedIP, IPAddress, SegmentUUID, Service, VideoID, VideoIDHash } from '../types/segments.model';
|
import { Category, CategoryActionType, HashedIP, IPAddress, SegmentUUID, Service, VideoID, VideoIDHash } from '../types/segments.model';
|
||||||
import { getCategoryActionType } from '../utils/categoryInfo';
|
import { getCategoryActionType } from '../utils/categoryInfo';
|
||||||
|
import { QueryCacher } from '../middleware/queryCacher';
|
||||||
|
|
||||||
const voteTypes = {
|
const voteTypes = {
|
||||||
normal: 0,
|
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);
|
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]);
|
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
|
//for each positive vote, see if a hidden submission can be shown again
|
||||||
if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) {
|
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'});
|
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user