pollo/src/server/api/routers/vote.ts
2023-08-12 19:28:31 -06:00

81 lines
2.2 KiB
TypeScript

import { z } from "zod";
import { publishToChannel } from "~/server/ably";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import { fetchCache, invalidateCache, setCache } from "~/server/redis";
import { EventTypes } from "~/utils/types";
import { eq } from "drizzle-orm";
import { votes } from "~/server/schema";
import { createId } from "@paralleldrive/cuid2";
export const voteRouter = createTRPCRouter({
getAllByRoomId: protectedProcedure
.input(z.object({ roomId: z.string() }))
.query(async ({ ctx, input }) => {
const cachedResult = await fetchCache<
{
id: string;
value: string;
created_at: Date;
userId: string;
roomId: string;
}[]
>(`kv_votes_${input.roomId}`);
if (cachedResult) {
return cachedResult;
} else {
const votesByRoomId = await ctx.db.query.votes.findMany({
where: eq(votes.roomId, input.roomId),
});
await setCache(`kv_votes_${input.roomId}`, votesByRoomId);
return votesByRoomId;
}
}),
set: protectedProcedure
.input(z.object({ value: z.string(), roomId: z.string() }))
.mutation(async ({ ctx, input }) => {
const updateResult = await ctx.db
.update(votes)
.set({
value: input.value,
userId: ctx.auth.userId,
roomId: input.roomId,
})
.where(eq(votes.userId, ctx.auth.userId));
let success = updateResult.rowsAffected > 0;
if (!success) {
const vote = await ctx.db.insert(votes).ignore().values({
id: createId(),
value: input.value,
userId: ctx.auth.userId,
roomId: input.roomId,
});
success = vote.rowsAffected > 0;
}
if (success) {
await invalidateCache(`kv_votecount`);
await invalidateCache(`kv_votes_${input.roomId}`);
await publishToChannel(
`${input.roomId}`,
EventTypes.VOTE_UPDATE,
input.value
);
await publishToChannel(
`stats`,
EventTypes.STATS_UPDATE,
JSON.stringify(success)
);
}
return success;
}),
});