aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRitesh Ghosh <[email protected]>2024-12-07 21:12:34 +0530
committerRitesh Ghosh <[email protected]>2024-12-07 21:12:34 +0530
commitb7d036dbe29fcfa39c6573a0f02888093eb43d78 (patch)
tree03541cdb97d45f439126cbadcd1505fb6a688b84 /src
parentdb022185efd04d4382883de543d3f3399cd28a6b (diff)
downloadaniwatch-api-b7d036dbe29fcfa39c6573a0f02888093eb43d78.tar.xz
aniwatch-api-b7d036dbe29fcfa39c6573a0f02888093eb43d78.zip
feat(cache): add `AniwatchAPICache` class to implement API caching layer
Diffstat (limited to 'src')
-rw-r--r--src/config/cache.ts50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/config/cache.ts b/src/config/cache.ts
new file mode 100644
index 0000000..6953fbc
--- /dev/null
+++ b/src/config/cache.ts
@@ -0,0 +1,50 @@
+import { config } from "dotenv";
+import { Redis } from "ioredis";
+
+config();
+
+export class AniwatchAPICache {
+ private _client: Redis | null;
+ public isOptional: boolean = true;
+
+ static DEFAULT_CACHE_EXPIRY_SECONDS = 60 as const;
+ static CACHE_EXPIRY_HEADER_NAME = "X-ANIWATCH-CACHE-EXPIRY" as const;
+
+ constructor() {
+ const redisConnURL = process.env?.ANIWATCH_API_REDIS_CONN_URL;
+ this.isOptional = !Boolean(redisConnURL);
+ this._client = this.isOptional ? null : new Redis(String(redisConnURL));
+ }
+
+ set(key: string | Buffer, value: string | Buffer | number) {
+ if (this.isOptional) return;
+ return this._client?.set(key, value);
+ }
+
+ get(key: string | Buffer) {
+ if (this.isOptional) return;
+ return this._client?.get(key);
+ }
+
+ /**
+ * @param expirySeconds set to 60 by default
+ */
+ async getOrSet<T>(
+ key: string | Buffer,
+ setCB: () => Promise<T>,
+ expirySeconds: number = AniwatchAPICache.DEFAULT_CACHE_EXPIRY_SECONDS
+ ) {
+ const cachedData = this.isOptional
+ ? null
+ : (await this._client?.get(key)) || null;
+ let data = JSON.parse(String(cachedData)) as T;
+
+ if (!data) {
+ data = await setCB();
+ await this._client?.set(key, JSON.stringify(data), "EX", expirySeconds);
+ }
+ return data;
+ }
+}
+
+export const cache = new AniwatchAPICache();