229 lines
6.8 KiB
TypeScript
229 lines
6.8 KiB
TypeScript
import { dbApiPostData } from "$lib/server/db/apipostdata.db";
|
|
import { dbApiUser } from "$lib/server/db/apiuser.db";
|
|
import { postDataToApi } from "$lib/server/postdata/post.handler";
|
|
import { getAllSessions } from "$lib/server/utils/session.service";
|
|
import { getULID } from "$lib/utils";
|
|
import {
|
|
type APISession,
|
|
type ServerError,
|
|
zPostDataEntry,
|
|
zPostDataFilters,
|
|
zPostDataHistoryFilters,
|
|
} from "$lib/utils/data.types";
|
|
import { createTRPCRouter, protectedProcedure } from "../t";
|
|
import { z } from "zod";
|
|
import {
|
|
fetchDataForPosting,
|
|
fetchPostDataHistory,
|
|
updateBalanceOfPostUsers,
|
|
} from "$lib/server/postdata/postdata.gen.controller";
|
|
import { redis } from "$lib/server/connectors/redis";
|
|
import { constants } from "$lib/utils/constants";
|
|
|
|
async function hasPostSession() {
|
|
const out = await redis.get(constants.POST_SESSION_KEY);
|
|
if (out === null) {
|
|
await redis.set(constants.POST_SESSION_KEY, "1");
|
|
return false;
|
|
}
|
|
return out === "1";
|
|
}
|
|
|
|
async function removePostSession() {
|
|
await redis.del(constants.POST_SESSION_KEY);
|
|
}
|
|
|
|
const postDataCacheStore = {
|
|
get: async (key: string) => {
|
|
return JSON.parse((await redis.get(`pdcc:${key}`)) ?? "[]");
|
|
},
|
|
set: async (key: string, data: any) => {
|
|
await redis.setex(`pdcc:${key}`, 60 * 60 * 1, JSON.stringify(data));
|
|
},
|
|
del: async (key: string) => {
|
|
await redis.del(`pdcc:${key}`);
|
|
},
|
|
};
|
|
|
|
export const postDataApiRouter = createTRPCRouter({
|
|
fetchPostDataHistory: protectedProcedure
|
|
.input(zPostDataHistoryFilters)
|
|
.mutation(async ({ input }) => {
|
|
return await fetchPostDataHistory(input);
|
|
}),
|
|
|
|
hasPosted: protectedProcedure
|
|
.input(zPostDataHistoryFilters)
|
|
.query(async ({ input }) => {
|
|
return {
|
|
hasPosted: await dbApiPostData.doesPostHistoryDataExist(
|
|
input.date,
|
|
input.draw?.id ?? "",
|
|
),
|
|
};
|
|
}),
|
|
|
|
getPostDataForPreview: protectedProcedure
|
|
.input(zPostDataFilters)
|
|
.query(async ({ input }) => {
|
|
const date = input.date;
|
|
const cacheKey = getULID();
|
|
if (!input.draw) {
|
|
return {
|
|
ok: false,
|
|
detail: "Draw is required",
|
|
data: [],
|
|
errors: undefined,
|
|
key: cacheKey,
|
|
};
|
|
}
|
|
|
|
console.log("[+] Fetching the users with updated balances");
|
|
const balOut = await updateBalanceOfPostUsers(
|
|
await dbApiUser.getAllPostUsersWithParentUsers(),
|
|
);
|
|
if (!balOut.ok || !balOut.data) {
|
|
return {
|
|
ok: false,
|
|
key: cacheKey,
|
|
detail: balOut.detail,
|
|
data: [],
|
|
users: [],
|
|
};
|
|
}
|
|
const users = balOut.data;
|
|
console.log(`[=] ${users.length} users found`);
|
|
console.log(users);
|
|
|
|
const result = await fetchDataForPosting(date, input, users);
|
|
postDataCacheStore.set(cacheKey, result.data).catch(console.error);
|
|
console.log("result.data.length = ", result.data.length);
|
|
return { ...result, key: cacheKey };
|
|
}),
|
|
|
|
post: protectedProcedure
|
|
.input(z.object({ yes: zPostDataFilters, cachedDataKey: z.string() }))
|
|
.mutation(async ({ input }) => {
|
|
if (await hasPostSession()) {
|
|
return {
|
|
ok: false,
|
|
detail:
|
|
"Already posting data, please wait for the current session to finish",
|
|
errors: [
|
|
{
|
|
message:
|
|
"Already posting data, please wait for the current session to finish",
|
|
},
|
|
] as ServerError,
|
|
};
|
|
}
|
|
const date = input.yes.date;
|
|
const draw = input.yes.draw;
|
|
if (!draw) {
|
|
await removePostSession();
|
|
return {
|
|
ok: false,
|
|
detail: "Draw is required",
|
|
errors: [{ message: "Draw is required" }] as ServerError,
|
|
};
|
|
}
|
|
const drawId = draw.id;
|
|
|
|
console.log("[+] Fetching the users");
|
|
const users = await dbApiUser.getAllPostUsersWithParentUsers();
|
|
console.log(users);
|
|
const balOut = await updateBalanceOfPostUsers(users);
|
|
if (!balOut.ok || !balOut.data) {
|
|
await removePostSession();
|
|
return { ok: false, detail: balOut.detail, data: [], users: [] };
|
|
}
|
|
console.log(`[=] ${users} users found`);
|
|
console.log(users);
|
|
|
|
console.log("[+] Preparing the sessions for posting");
|
|
const sessions = await getAllSessions();
|
|
const userSessions = {} as Record<string, APISession>;
|
|
for (const each of sessions) {
|
|
const targetUser = users.find(
|
|
(u) => each.key.includes(u.id) || each.value.userId === u.userId,
|
|
);
|
|
if (!targetUser) continue;
|
|
userSessions[targetUser?.userId ?? ""] = each.value;
|
|
}
|
|
|
|
if (Object.keys(userSessions).length !== users.length) {
|
|
await removePostSession();
|
|
return {
|
|
ok: false,
|
|
detail: `Some users don't have a session to post data with`,
|
|
errors: [
|
|
{ message: "Some users don't have a session to post data with" },
|
|
],
|
|
};
|
|
}
|
|
|
|
let data: any[] = await postDataCacheStore.get(input.cachedDataKey);
|
|
console.log("cached.data.length = ", data.length);
|
|
if (data.length < 1) {
|
|
console.log("No data found from preview, generating a list");
|
|
const _out = await fetchDataForPosting(date, input.yes, balOut.data);
|
|
if (!_out.ok) {
|
|
await removePostSession();
|
|
return _out;
|
|
}
|
|
data = _out.data;
|
|
console.log("data.length = ", data.length);
|
|
}
|
|
|
|
if (data.length < 1) {
|
|
await removePostSession();
|
|
return {
|
|
ok: false,
|
|
detail: "No data found to post for the selected date and draw",
|
|
errors: [
|
|
{ message: "No data found to post for the selected date and draw" },
|
|
],
|
|
};
|
|
}
|
|
|
|
console.log(`[+] Posting ${data.length} entries to the API`);
|
|
|
|
const res = await postDataToApi({
|
|
sessions: userSessions,
|
|
data,
|
|
users: users,
|
|
draw: draw,
|
|
});
|
|
console.timeEnd("Time taken to post data to the API");
|
|
|
|
if (!res.ok) {
|
|
await removePostSession();
|
|
return { ok: false, detail: res.detail };
|
|
}
|
|
|
|
console.log(`[+] Data posted to the API successfully`);
|
|
|
|
await dbApiPostData.upsertData({
|
|
id: getULID(),
|
|
drawId: +drawId.split(":")[1],
|
|
bookDate: date,
|
|
data,
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
});
|
|
|
|
// Update the balance of the users after posting to the API
|
|
await updateBalanceOfPostUsers(users);
|
|
|
|
console.log("[+] Data saved to the database");
|
|
|
|
await postDataCacheStore.del(input.cachedDataKey);
|
|
await removePostSession();
|
|
return {
|
|
ok: true,
|
|
detail: "Data successfully posted to API",
|
|
errors: undefined,
|
|
};
|
|
}),
|
|
});
|