This commit is contained in:
Atridad Lahiji 2023-05-21 20:02:51 -06:00
parent 9b41ec97bc
commit d69aca793e
No known key found for this signature in database
8 changed files with 140 additions and 104 deletions

View file

@ -1,6 +1,6 @@
{
"name": "sprintpadawan",
"version": "1.0.2",
"version": "1.0.3",
"description": "Plan. Sprint. Repeat.",
"private": true,
"scripts": {
@ -25,8 +25,7 @@
"ably": "^1.2.39",
"autoprefixer": "^10.4.14",
"daisyui": "^2.51.6",
"fms-ts": "^0.1.6",
"ioredis": "^5.3.2",
"fms-ts": "^0.1.7",
"json2csv": "6.0.0-alpha.2",
"next": "^13.4.3",
"next-auth": "^4.22.1",
@ -35,13 +34,14 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"redicache-ts": "^0.1.1",
"superjson": "1.12.3",
"tailwindcss": "^3.3.2",
"zod": "^3.21.4"
},
"devDependencies": {
"@types/eslint": "^8.37.0",
"@types/node": "^20.2.1",
"@types/node": "^20.2.3",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@typescript-eslint/eslint-plugin": "^5.59.6",

58
pnpm-lock.yaml generated
View file

@ -44,11 +44,8 @@ dependencies:
specifier: ^2.51.6
version: 2.51.6(autoprefixer@10.4.14)(postcss@8.4.23)
fms-ts:
specifier: ^0.1.6
version: 0.1.6
ioredis:
specifier: ^5.3.2
version: 5.3.2
specifier: ^0.1.7
version: 0.1.7
json2csv:
specifier: 6.0.0-alpha.2
version: 6.0.0-alpha.2
@ -73,6 +70,9 @@ dependencies:
react-icons:
specifier: ^4.8.0
version: 4.8.0(react@18.2.0)
redicache-ts:
specifier: ^0.1.1
version: 0.1.1
superjson:
specifier: 1.12.3
version: 1.12.3
@ -88,8 +88,8 @@ devDependencies:
specifier: ^8.37.0
version: 8.37.0
'@types/node':
specifier: ^20.2.1
version: 20.2.1
specifier: ^20.2.3
version: 20.2.3
'@types/react':
specifier: ^18.2.6
version: 18.2.6
@ -1747,7 +1747,7 @@ packages:
dependencies:
'@types/http-cache-semantics': 4.0.1
'@types/keyv': 3.1.4
'@types/node': 20.2.1
'@types/node': 20.2.3
'@types/responselike': 1.0.0
dev: false
@ -1775,7 +1775,7 @@ packages:
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
dependencies:
'@types/minimatch': 5.1.2
'@types/node': 20.2.1
'@types/node': 20.2.3
dev: false
/@types/http-cache-semantics@4.0.1:
@ -1788,7 +1788,7 @@ packages:
/@types/json2csv@5.0.3:
resolution: {integrity: sha512-ZJEv6SzhPhgpBpxZU4n/TZekbZqI4EcyXXRwms1lAITG2kIAtj85PfNYafUOY1zy8bWs5ujaub0GU4copaA0sw==}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
dev: false
/@types/json5@0.0.29:
@ -1798,7 +1798,7 @@ packages:
/@types/keyv@3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
dev: false
/@types/minimatch@5.1.2:
@ -1824,8 +1824,8 @@ packages:
- supports-color
dev: false
/@types/node@20.2.1:
resolution: {integrity: sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg==}
/@types/node@20.2.3:
resolution: {integrity: sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==}
/@types/prop-types@15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
@ -1846,13 +1846,13 @@ packages:
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
dev: false
/@types/responselike@1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
dev: false
/@types/scheduler@0.16.3:
@ -3369,8 +3369,8 @@ packages:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true
/fms-ts@0.1.6:
resolution: {integrity: sha512-udJ0KwyFEIF27DQDl0PUptyTYrWczBr8P9g/b4j+Zri4cxQZcKCqcLfHUeDaD8usoThpk4WO0jVjftcjs9fYRw==}
/fms-ts@0.1.7:
resolution: {integrity: sha512-OLmulPKywj1ETsAGeNTaxOmrFdffLFr97Gc/Bfmwu80mS1ToyvTDGNcMa16rCScBabd7M+UlCDSgpafjrTyCJw==}
dev: false
/for-each@0.3.3:
@ -3941,7 +3941,7 @@ packages:
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
merge-stream: 2.0.0
supports-color: 7.2.0
dev: false
@ -3950,7 +3950,7 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 20.2.1
'@types/node': 20.2.3
merge-stream: 2.0.0
supports-color: 8.1.1
dev: false
@ -4302,8 +4302,8 @@ packages:
next: 13.4.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0)
oauth: 0.9.15
openid-client: 5.4.2
preact: 10.14.1
preact-render-to-string: 5.2.6(preact@10.14.1)
preact: 10.15.0
preact-render-to-string: 5.2.6(preact@10.15.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
uuid: 8.3.2
@ -4747,17 +4747,17 @@ packages:
source-map-js: 1.0.2
dev: false
/preact-render-to-string@5.2.6(preact@10.14.1):
/preact-render-to-string@5.2.6(preact@10.15.0):
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
peerDependencies:
preact: '>=10'
dependencies:
preact: 10.14.1
preact: 10.15.0
pretty-format: 3.8.0
dev: false
/preact@10.14.1:
resolution: {integrity: sha512-4XDSnUisk3YFBb3p9WeKeH1mKoxdFUsaXcvxs9wlpYR1wax/TWJVqhwmIWbByX0h7jMEJH6Zc5J6jqc58FKaNQ==}
/preact@10.15.0:
resolution: {integrity: sha512-nZSa8M2R2m1n7nJSBlzDpxRJaIsejrTO1vlFbdpFvyC8qM1iU+On2y0otfoUm6SRB5o0lF0CKDFxg6grEFU0iQ==}
dev: false
/prelude-ls@1.2.1:
@ -4865,6 +4865,14 @@ packages:
picomatch: 2.3.1
dev: false
/redicache-ts@0.1.1:
resolution: {integrity: sha512-z6edrqsRlayBhI91eA8/N+AGJeFAdU+tvnmP3LzAyQ5pqXEM9Ww1+bHTKd0pWRRcZMWKLaaAHx9SOWj/IEfpuw==}
dependencies:
ioredis: 5.3.2
transitivePeerDependencies:
- supports-color
dev: false
/redis-errors@1.2.0:
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
engines: {node: '>=4'}

View file

@ -7,7 +7,15 @@ import {
protectedProcedure,
} from "~/server/api/trpc";
import { writeToCache, fetchFromCache, deleteFromCache } from "~/server/redis";
import {
cacheClient,
writeToCache,
fetchFromCache,
deleteFromCache,
} from "redicache-ts";
import { env } from "~/env.mjs";
const client = cacheClient(env.REDIS_URL);
export const roomRouter = createTRPCRouter({
// Create
@ -29,8 +37,12 @@ export const roomRouter = createTRPCRouter({
},
});
if (room) {
await deleteFromCache(`kv_roomcount_admin`);
await deleteFromCache(`kv_roomlist_${ctx.session.user.id}`);
await deleteFromCache(client, env.APP_ENV, `kv_roomcount_admin`);
await deleteFromCache(
client,
env.APP_ENV,
`kv_roomlist_${ctx.session.user.id}`
);
await publishToChannel(
`${ctx.session.user.id}`,
@ -92,7 +104,7 @@ export const roomRouter = createTRPCRouter({
createdAt: Date;
roomName: string;
}[]
>(`kv_roomlist_${ctx.session.user.id}`);
>(client, env.APP_ENV, `kv_roomlist_${ctx.session.user.id}`);
if (cachedResult) {
return cachedResult;
@ -109,6 +121,8 @@ export const roomRouter = createTRPCRouter({
});
await writeToCache(
client,
env.APP_ENV,
`kv_roomlist_${ctx.session.user.id}`,
JSON.stringify(roomList),
69
@ -119,14 +133,24 @@ export const roomRouter = createTRPCRouter({
}),
countAll: protectedProcedure.query(async ({ ctx }) => {
const cachedResult = await fetchFromCache<number>(`kv_roomcount_admin`);
const cachedResult = await fetchFromCache<number>(
client,
env.APP_ENV,
`kv_roomcount_admin`
);
if (cachedResult) {
return cachedResult;
} else {
const roomsCount = await ctx.prisma.room.count();
await writeToCache(`kv_roomcount_admin`, roomsCount, 69);
await writeToCache(
client,
env.APP_ENV,
`kv_roomcount_admin`,
roomsCount,
69
);
return roomsCount;
}
@ -242,9 +266,13 @@ export const roomRouter = createTRPCRouter({
});
if (deletedRoom) {
await deleteFromCache(`kv_roomcount_admin`);
await deleteFromCache(`kv_votecount_admin`);
await deleteFromCache(`kv_roomlist_${ctx.session.user.id}`);
await deleteFromCache(client, env.APP_ENV, `kv_roomcount_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_votecount_admin`);
await deleteFromCache(
client,
env.APP_ENV,
`kv_roomlist_${ctx.session.user.id}`
);
await publishToChannel(
`${ctx.session.user.id}`,

View file

@ -1,6 +1,9 @@
import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import { deleteFromCache } from "~/server/redis";
import { cacheClient, deleteFromCache } from "redicache-ts";
import { env } from "~/env.mjs";
const client = cacheClient(env.REDIS_URL);
export const sessionRouter = createTRPCRouter({
deleteAll: protectedProcedure
@ -17,7 +20,7 @@ export const sessionRouter = createTRPCRouter({
});
if (!!sessions) {
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
}
return !!sessions;

View file

@ -3,19 +3,37 @@ import { z } from "zod";
import { env } from "~/env.mjs";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import { sendMail } from "fms-ts";
import { fetchFromCache, writeToCache, deleteFromCache } from "~/server/redis";
import type { Role } from "~/utils/types";
import {
cacheClient,
writeToCache,
fetchFromCache,
deleteFromCache,
} from "redicache-ts";
const client = cacheClient(env.REDIS_URL);
export const userRouter = createTRPCRouter({
countAll: protectedProcedure.query(async ({ ctx }) => {
const cachedResult = await fetchFromCache<number>(`kv_usercount_admin`);
const cachedResult = await fetchFromCache<number>(
client,
env.APP_ENV,
`kv_usercount_admin`
);
if (cachedResult) {
return cachedResult;
} else {
const usersCount = await ctx.prisma.user.count();
await writeToCache(`kv_usercount_admin`, usersCount, 69);
await writeToCache(
client,
env.APP_ENV,
`kv_usercount_admin`,
usersCount,
69
);
return usersCount;
}
@ -50,7 +68,7 @@ export const userRouter = createTRPCRouter({
name: string | null;
email: string | null;
}[]
>(`kv_userlist_admin`);
>(client, env.APP_ENV, `kv_userlist_admin`);
if (cachedResult) {
return cachedResult.map((user) => {
@ -75,7 +93,13 @@ export const userRouter = createTRPCRouter({
},
});
await writeToCache(`kv_userlist_admin`, JSON.stringify(users), 69);
await writeToCache(
client,
env.APP_ENV,
`kv_userlist_admin`,
JSON.stringify(users),
69
);
return users;
}
@ -121,8 +145,8 @@ export const userRouter = createTRPCRouter({
body,
user.email
);
await deleteFromCache(`kv_usercount_admin`);
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_usercount_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
}
return !!user;
@ -162,7 +186,7 @@ export const userRouter = createTRPCRouter({
},
});
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
return !!user;
}),

View file

@ -2,18 +2,36 @@ import { z } from "zod";
import { publishToChannel } from "~/server/ably";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import { deleteFromCache, fetchFromCache, writeToCache } from "~/server/redis";
import {
cacheClient,
writeToCache,
fetchFromCache,
deleteFromCache,
} from "redicache-ts";
import { env } from "~/env.mjs";
const client = cacheClient(env.REDIS_URL);
export const voteRouter = createTRPCRouter({
countAll: protectedProcedure.query(async ({ ctx }) => {
const cachedResult = await fetchFromCache<number>(`kv_votecount_admin`);
const cachedResult = await fetchFromCache<number>(
client,
env.APP_ENV,
`kv_votecount_admin`
);
if (cachedResult) {
return cachedResult;
} else {
const votesCount = await ctx.prisma.vote.count();
await writeToCache(`kv_votecount_admin`, votesCount, 69);
await writeToCache(
client,
env.APP_ENV,
`kv_votecount_admin`,
votesCount,
69
);
return votesCount;
}
@ -52,7 +70,7 @@ export const voteRouter = createTRPCRouter({
});
if (vote) {
await deleteFromCache(`kv_votecount_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_votecount_admin`);
await publishToChannel(`${vote.roomId}`, "VOTE_UPDATE", "UPDATE");
}

View file

@ -11,7 +11,9 @@ import { env } from "~/env.mjs";
import { prisma } from "~/server/db";
import type { Role } from "~/utils/types";
import { sendMail } from "fms-ts";
import { deleteFromCache } from "./redis";
import { cacheClient, deleteFromCache } from "redicache-ts";
const client = cacheClient(env.REDIS_URL);
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
@ -66,15 +68,15 @@ export const authOptions: NextAuthOptions = {
body,
user.email
);
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(`kv_usercount_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_usercount_admin`);
}
},
async signIn({}) {
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
},
async signOut({}) {
await deleteFromCache(`kv_userlist_admin`);
await deleteFromCache(client, env.APP_ENV, `kv_userlist_admin`);
},
},
adapter: PrismaAdapter(prisma),

View file

@ -1,47 +0,0 @@
import { Redis } from "ioredis";
import { env } from "~/env.mjs";
export const redis = new Redis(env.REDIS_URL);
export const writeToCache = async (
key: string,
value: string | number | Buffer,
timeout?: number
): Promise<boolean> => {
try {
if (!!timeout) {
await redis.set(`${env.APP_ENV}_${key}`, value, "EX", timeout);
} else {
await redis.set(`${env.APP_ENV}_${key}`, value);
}
return true;
} catch {
return false;
}
};
export const fetchFromCache = async <T>(key: string): Promise<T | null> => {
try {
// This is bad please don't ever do this.
const cachedValue: Awaited<T> | null = JSON.parse(
(await redis.get(`${env.APP_ENV}_${key}`)) || ""
) as Awaited<T> | null;
if (!cachedValue && cachedValue !== 0) {
throw new Error("Cache Miss");
}
console.log(`CACHE HIT FOR KEY ${key}: `, cachedValue);
return cachedValue;
} catch {
console.log(`CACHE MISS FOR KEY ${key}!`);
return null;
}
};
export const deleteFromCache = async (key: string) => {
try {
await redis.del(`${env.APP_ENV}_${key}`);
return true;
} catch {
return false;
}
};