From ebfc5327c0d4920c1e5b45cf43db6716012ddc1d Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 21:39:54 +0530 Subject: [PATCH 01/11] fix: remove unused function --- frontend/src/SearchResults.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/SearchResults.tsx b/frontend/src/SearchResults.tsx index 2b60ee9e..efd011d2 100644 --- a/frontend/src/SearchResults.tsx +++ b/frontend/src/SearchResults.tsx @@ -1,5 +1,5 @@ import { queryOptions, useQuery } from "@tanstack/react-query"; -import { ErrorComponent, Route, notFound } from "@tanstack/react-router"; +import { ErrorComponent, Route } from "@tanstack/react-router"; import axios, { AxiosError } from "axios"; import { z } from "zod"; import { timetableWithSectionsType } from "../../lib/src"; From d9ceb7134ed84acd080d49804002062dffc40c1e Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 21:41:08 +0530 Subject: [PATCH 02/11] feat: create `addTimetable` util function --- backend/src/utils/search.ts | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 backend/src/utils/search.ts diff --git a/backend/src/utils/search.ts b/backend/src/utils/search.ts new file mode 100644 index 00000000..10f37a20 --- /dev/null +++ b/backend/src/utils/search.ts @@ -0,0 +1,51 @@ +import "dotenv/config"; +import { Logger } from "pino"; +import { env } from "../config/server.js"; +import { Timetable } from "../entity/entities.js"; +import { userRepository } from "../repositories/userRepository.js"; +import sqids from "./sqids.js"; + +export const addTimetable = async ( + timetable: Timetable, + authorEmail: string | null, + logger: Logger | Console, +) => { + try { + const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/add`; + const encodedId = sqids.encode([timetable.id]); + const email = + authorEmail ?? + ( + await userRepository + .createQueryBuilder("user") + .where("user.id = :id", { id: timetable.authorId }) + .getOneOrFail() + ).email; + const authorId = email.slice(0, 9); + const modifiedTimetable = { + ...timetable, + id: encodedId, + authorId, + }; + const res = await fetch(searchServiceURL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(modifiedTimetable), + }); + const resJson = await res.json(); + if (!res.ok) { + logger.error( + "Error while adding timetable to search service: ", + resJson.error, + ); + } + } catch (err: any) { + logger.error( + "Error while adding timetable to search service: ", + err.message, + ); + throw err; + } +}; From 7ca6dea1b55b8430345b0c6b8e363cd128df6d93 Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 22:06:22 +0530 Subject: [PATCH 03/11] feat: use util function --- .../timetable/editTimetableMetadata.ts | 25 ++------------ .../timetable/updateChangedTimetable.ts | 26 +++----------- backend/src/ingestJSON.ts | 34 +++++-------------- 3 files changed, 15 insertions(+), 70 deletions(-) diff --git a/backend/src/controllers/timetable/editTimetableMetadata.ts b/backend/src/controllers/timetable/editTimetableMetadata.ts index f49a4921..29da5948 100644 --- a/backend/src/controllers/timetable/editTimetableMetadata.ts +++ b/backend/src/controllers/timetable/editTimetableMetadata.ts @@ -11,6 +11,7 @@ import { Timetable, User } from "../../entity/entities.js"; import { validate } from "../../middleware/zodValidateRequest.js"; import { timetableRepository } from "../../repositories/timetableRepository.js"; import { userRepository } from "../../repositories/userRepository.js"; +import { addTimetable } from "../../utils/search.js"; import sqids, { validSqid } from "../../utils/sqids.js"; const dataSchema = z.object({ @@ -119,30 +120,8 @@ export const editTimetableMetadata = async (req: Request, res: Response) => { if (isDraft === false && isPrivate === false) { try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/add`; - const updatedTimetableStringID = { - ...updatedTimetable, - id: req.params.id, - }; - const res = await fetch(searchServiceURL, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(updatedTimetableStringID), - }); - const resJson = await res.json(); - if (!res.ok) { - logger.error( - "Error while adding timetable to search service: ", - resJson.error, - ); - } + addTimetable(updatedTimetable, req.session?.email ?? "", logger); } catch (err: any) { - logger.error( - "Error while adding timetable to search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } } else { diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index db9173f5..e267e107 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -15,6 +15,7 @@ import { checkForClassHoursClash, checkForExamHoursClash, } from "../../utils/checkForClashes.js"; +import { addTimetable } from "../../utils/search.js"; import sqids from "../../utils/sqids.js"; import { addExamTimings, removeSection } from "../../utils/updateSection.js"; import { updateSectionWarnings } from "../../utils/updateWarnings.js"; @@ -312,29 +313,10 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { const timetableWithSections = await timetableRepository .createQueryBuilder("timetable") .leftJoinAndSelect("timetable.sections", "section") - .where("timetable.id=:id", { id: timetable.id }) - .getOne(); - const encodedId = sqids.encode([timetable.id]); - const timetableWithSectionsString = { - ...timetableWithSections, - id: encodedId, - }; + .where("timetable.id = :id", { id: timetable.id }) + .getOneOrFail(); try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/add`; - const res = await fetch(searchServiceURL, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(timetableWithSectionsString), - }); - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while adding timetable to search service: ", - resJson.error, - ); - } + addTimetable(timetableWithSections, null, logger); } catch (err: any) { logger.error( "Error while adding timetable to search service: ", diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index 8ceb6815..7c869e9a 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -2,6 +2,7 @@ import { QueryRunner } from "typeorm"; import { sectionTypeEnum } from "../../lib/src/index.js"; import { env } from "./config/server.js"; import { Course, Section, Timetable } from "./entity/entities.js"; +import { addTimetable } from "./utils/search.js"; import sqids from "./utils/sqids.js"; interface ExamJSON { @@ -427,32 +428,15 @@ export const ingestJSON = async ( `error while removing timetable ${id} from search service: ${err.message}`, ); } - const timetable = await queryRunner.manager - .createQueryBuilder() - .select("timetable") - .from(Timetable, "timetable") - .leftJoinAndSelect("timetable.sections", "section") - .where("timetable.id = :id", { id }) - .getOne(); - const timetableWithSqid = { - ...timetable, - id: encodedId, - }; try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/add`; - const res = await fetch(searchServiceURL, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(timetableWithSqid), - }); - if (!res.ok) { - const resJson = await res.json(); - console.log( - `error while adding timetable ${id} to search service: ${resJson.error}`, - ); - } + const timetable = await queryRunner.manager + .createQueryBuilder() + .select("timetable") + .from(Timetable, "timetable") + .leftJoinAndSelect("timetable.sections", "section") + .where("timetable.id = :id", { id }) + .getOneOrFail(); + addTimetable(timetable, null, console); } catch (err: any) { console.log( `error while adding timetable ${id} to search service: ${err.message}`, From 7cb6d8d8bc966c01d717303d4acc86cbfc29dd9c Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 22:17:46 +0530 Subject: [PATCH 04/11] feat: add remove timetable function --- backend/src/utils/search.ts | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/backend/src/utils/search.ts b/backend/src/utils/search.ts index 10f37a20..18e06a58 100644 --- a/backend/src/utils/search.ts +++ b/backend/src/utils/search.ts @@ -34,8 +34,8 @@ export const addTimetable = async ( }, body: JSON.stringify(modifiedTimetable), }); - const resJson = await res.json(); if (!res.ok) { + const resJson = await res.json(); logger.error( "Error while adding timetable to search service: ", resJson.error, @@ -49,3 +49,33 @@ export const addTimetable = async ( throw err; } }; + +export const removeTimetable = async ( + timetableId: number, + logger: Logger | Console, +) => { + try { + const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/remove`; + const encodedId = sqids.encode([timetableId]); + const res = await fetch(searchServiceURL, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ id: encodedId }), + }); + if (!res.ok) { + const resJson = await res.json(); + logger.error( + "Error while removing timetable from search service: ", + resJson.error, + ); + } + } catch (err: any) { + logger.error( + "Error while removing timetable from search service: ", + err.message, + ); + throw err; + } +}; From 4c00c816e9d54ec998b268ee49951e292b406e7d Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 22:32:35 +0530 Subject: [PATCH 05/11] feat: use remove timetable function --- .../controllers/timetable/deleteTimetable.ts | 22 ++------------ .../timetable/editTimetableMetadata.ts | 23 ++------------ .../timetable/updateChangedTimetable.ts | 28 ++--------------- backend/src/ingestJSON.ts | 30 ++----------------- 4 files changed, 8 insertions(+), 95 deletions(-) diff --git a/backend/src/controllers/timetable/deleteTimetable.ts b/backend/src/controllers/timetable/deleteTimetable.ts index 1de51a97..8b4dcb7e 100644 --- a/backend/src/controllers/timetable/deleteTimetable.ts +++ b/backend/src/controllers/timetable/deleteTimetable.ts @@ -8,6 +8,7 @@ import { validate } from "../../middleware/zodValidateRequest.js"; import { timetableRepository } from "../../repositories/timetableRepository.js"; import { userRepository } from "../../repositories/userRepository.js"; import sqids, { validSqid } from "../../utils/sqids.js"; +import { removeTimetable } from "../../utils/search.js"; const dataSchema = z.object({ params: z.object({ @@ -74,27 +75,8 @@ export const deleteTimetable = async (req: Request, res: Response) => { res.status(500).json({ message: "Internal Server Error" }); } try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/remove`; - - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: req.params.id }), - }); - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while removing timetable from search service: ", - resJson.error, - ); - } + removeTimetable(timetable.id, logger); } catch (err: any) { - logger.error( - "Error while removing timetable from search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } return res.json({ message: "timetable deleted" }); diff --git a/backend/src/controllers/timetable/editTimetableMetadata.ts b/backend/src/controllers/timetable/editTimetableMetadata.ts index 29da5948..aaa6af7a 100644 --- a/backend/src/controllers/timetable/editTimetableMetadata.ts +++ b/backend/src/controllers/timetable/editTimetableMetadata.ts @@ -11,7 +11,7 @@ import { Timetable, User } from "../../entity/entities.js"; import { validate } from "../../middleware/zodValidateRequest.js"; import { timetableRepository } from "../../repositories/timetableRepository.js"; import { userRepository } from "../../repositories/userRepository.js"; -import { addTimetable } from "../../utils/search.js"; +import { addTimetable, removeTimetable } from "../../utils/search.js"; import sqids, { validSqid } from "../../utils/sqids.js"; const dataSchema = z.object({ @@ -126,27 +126,8 @@ export const editTimetableMetadata = async (req: Request, res: Response) => { } } else { try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/remove`; - - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: req.params.id }), - }); - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while removing timetable from search service: ", - resJson.error, - ); - } + removeTimetable(timetable.id, logger); } catch (err: any) { - logger.error( - "Error while removing timetable from search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } } diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index e267e107..70343f52 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -15,7 +15,7 @@ import { checkForClassHoursClash, checkForExamHoursClash, } from "../../utils/checkForClashes.js"; -import { addTimetable } from "../../utils/search.js"; +import { addTimetable, removeTimetable } from "../../utils/search.js"; import sqids from "../../utils/sqids.js"; import { addExamTimings, removeSection } from "../../utils/updateSection.js"; import { updateSectionWarnings } from "../../utils/updateWarnings.js"; @@ -285,28 +285,8 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { // update timetables in search service for (const timetable of timetables) { try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/remove`; - const encodedId = sqids.encode([timetable.id]); - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: encodedId }), - }); - - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while removing timetable from search service: ", - resJson.error, - ); - } + removeTimetable(timetable.id, logger); } catch (err: any) { - logger.error( - "Error while removing timetable from search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } if (!timetable.draft && !timetable.private) { @@ -318,10 +298,6 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { try { addTimetable(timetableWithSections, null, logger); } catch (err: any) { - logger.error( - "Error while adding timetable to search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } } diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index 7c869e9a..c13ef8f8 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -2,7 +2,7 @@ import { QueryRunner } from "typeorm"; import { sectionTypeEnum } from "../../lib/src/index.js"; import { env } from "./config/server.js"; import { Course, Section, Timetable } from "./entity/entities.js"; -import { addTimetable } from "./utils/search.js"; +import { addTimetable, removeTimetable } from "./utils/search.js"; import sqids from "./utils/sqids.js"; interface ExamJSON { @@ -407,28 +407,7 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${timetableCount} timetables are to be updated`); for (const { id } of timetableIds) { - const encodedId = sqids.encode([id]); - try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/timetable/remove`; - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: encodedId }), - }); - if (!res.ok) { - const resJson = await res.json(); - console.log( - `error while removing timetable ${id} from search service: ${resJson.error}`, - ); - } - } catch (err: any) { - console.log( - `error while removing timetable ${id} from search service: ${err.message}`, - ); - } - try { + removeTimetable(id, console); const timetable = await queryRunner.manager .createQueryBuilder() .select("timetable") @@ -437,11 +416,6 @@ export const ingestJSON = async ( .where("timetable.id = :id", { id }) .getOneOrFail(); addTimetable(timetable, null, console); - } catch (err: any) { - console.log( - `error while adding timetable ${id} to search service: ${err.message}`, - ); - } } console.log("updated timetables in search service!"); From f51ba41078db3a2432b3c912b366392aa551ac5c Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 22:37:47 +0530 Subject: [PATCH 06/11] feat: better error messages --- backend/src/utils/search.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/src/utils/search.ts b/backend/src/utils/search.ts index 18e06a58..a02496ab 100644 --- a/backend/src/utils/search.ts +++ b/backend/src/utils/search.ts @@ -37,14 +37,14 @@ export const addTimetable = async ( if (!res.ok) { const resJson = await res.json(); logger.error( - "Error while adding timetable to search service: ", - resJson.error, + `Error while adding timetable ${timetable.id} to search service: ${resJson.error}`, ); } } catch (err: any) { logger.error( - "Error while adding timetable to search service: ", - err.message, + `Error while adding timetable ${timetable.id} to search service: ${ + "message" in err ? err.message : err + }`, ); throw err; } @@ -67,14 +67,14 @@ export const removeTimetable = async ( if (!res.ok) { const resJson = await res.json(); logger.error( - "Error while removing timetable from search service: ", - resJson.error, + `Error while removing timetable ${timetableId} from search service: ${resJson.error}`, ); } } catch (err: any) { logger.error( - "Error while removing timetable from search service: ", - err.message, + `Error while removing timetable ${timetableId} from search service: ${ + "message" in err ? err.message : err + }`, ); throw err; } From 253837006ce1af99fdbacfb8bbbab546e6d4282b Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 23:00:17 +0530 Subject: [PATCH 07/11] style: remove unused imports --- .../controllers/timetable/deleteTimetable.ts | 3 +-- .../timetable/editTimetableMetadata.ts | 1 - .../timetable/updateChangedTimetable.ts | 1 - backend/src/ingestJSON.ts | 19 +++++++++---------- biome.json | 3 +++ 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/backend/src/controllers/timetable/deleteTimetable.ts b/backend/src/controllers/timetable/deleteTimetable.ts index 8b4dcb7e..a3e82361 100644 --- a/backend/src/controllers/timetable/deleteTimetable.ts +++ b/backend/src/controllers/timetable/deleteTimetable.ts @@ -2,13 +2,12 @@ import "dotenv/config"; import { Request, Response } from "express"; import { z } from "zod"; import { timetableIDType } from "../../../../lib/src/index.js"; -import { env } from "../../config/server.js"; import { Timetable, User } from "../../entity/entities.js"; import { validate } from "../../middleware/zodValidateRequest.js"; import { timetableRepository } from "../../repositories/timetableRepository.js"; import { userRepository } from "../../repositories/userRepository.js"; -import sqids, { validSqid } from "../../utils/sqids.js"; import { removeTimetable } from "../../utils/search.js"; +import sqids, { validSqid } from "../../utils/sqids.js"; const dataSchema = z.object({ params: z.object({ diff --git a/backend/src/controllers/timetable/editTimetableMetadata.ts b/backend/src/controllers/timetable/editTimetableMetadata.ts index aaa6af7a..171b5721 100644 --- a/backend/src/controllers/timetable/editTimetableMetadata.ts +++ b/backend/src/controllers/timetable/editTimetableMetadata.ts @@ -6,7 +6,6 @@ import { namedNonEmptyStringType, timetableIDType, } from "../../../../lib/src/index.js"; -import { env } from "../../config/server.js"; import { Timetable, User } from "../../entity/entities.js"; import { validate } from "../../middleware/zodValidateRequest.js"; import { timetableRepository } from "../../repositories/timetableRepository.js"; diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index 70343f52..6fd8bcf6 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -16,7 +16,6 @@ import { checkForExamHoursClash, } from "../../utils/checkForClashes.js"; import { addTimetable, removeTimetable } from "../../utils/search.js"; -import sqids from "../../utils/sqids.js"; import { addExamTimings, removeSection } from "../../utils/updateSection.js"; import { updateSectionWarnings } from "../../utils/updateWarnings.js"; diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index c13ef8f8..58f9a293 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -3,7 +3,6 @@ import { sectionTypeEnum } from "../../lib/src/index.js"; import { env } from "./config/server.js"; import { Course, Section, Timetable } from "./entity/entities.js"; import { addTimetable, removeTimetable } from "./utils/search.js"; -import sqids from "./utils/sqids.js"; interface ExamJSON { midsem: string | null; @@ -407,15 +406,15 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${timetableCount} timetables are to be updated`); for (const { id } of timetableIds) { - removeTimetable(id, console); - const timetable = await queryRunner.manager - .createQueryBuilder() - .select("timetable") - .from(Timetable, "timetable") - .leftJoinAndSelect("timetable.sections", "section") - .where("timetable.id = :id", { id }) - .getOneOrFail(); - addTimetable(timetable, null, console); + removeTimetable(id, console); + const timetable = await queryRunner.manager + .createQueryBuilder() + .select("timetable") + .from(Timetable, "timetable") + .leftJoinAndSelect("timetable.sections", "section") + .where("timetable.id = :id", { id }) + .getOneOrFail(); + addTimetable(timetable, null, console); } console.log("updated timetables in search service!"); diff --git a/biome.json b/biome.json index 41160249..627bce22 100644 --- a/biome.json +++ b/biome.json @@ -7,6 +7,9 @@ "enabled": true, "rules": { "recommended": true, + "nursery": { + "noUnusedImports": "error" + }, "suspicious": { "noExplicitAny": "off" } From 6d6dbb6094167aa7dd9006e6f6254f43d90d394b Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 23:17:17 +0530 Subject: [PATCH 08/11] feat: add course util functions --- .../timetable/updateChangedTimetable.ts | 47 +++------------ backend/src/ingestJSON.ts | 52 +++-------------- backend/src/utils/search.ts | 57 ++++++++++++++++++- 3 files changed, 73 insertions(+), 83 deletions(-) diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index 6fd8bcf6..a6c25b6e 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -15,7 +15,12 @@ import { checkForClassHoursClash, checkForExamHoursClash, } from "../../utils/checkForClashes.js"; -import { addTimetable, removeTimetable } from "../../utils/search.js"; +import { + addCourse, + addTimetable, + removeCourse, + removeTimetable, +} from "../../utils/search.js"; import { addExamTimings, removeSection } from "../../utils/updateSection.js"; import { updateSectionWarnings } from "../../utils/updateWarnings.js"; @@ -234,50 +239,14 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { // update course in search service try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/remove`; - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id: course.id }), - }); - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while removing course from search service: ", - resJson.error, - ); - } + removeCourse(course.id, logger); } catch (err: any) { - logger.error( - "Error while removing course from search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/add`; - const res = await fetch(searchServiceURL, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(course), - }); - if (!res.ok) { - const resJson = await res.json(); - logger.error( - "Error while adding course to search service: ", - resJson.error, - ); - } + addCourse(course, logger); } catch (err: any) { - logger.error( - "Error while adding course to search service: ", - err.message, - ); return res.status(500).json({ message: "Internal Server Error" }); } diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index 58f9a293..fe0ffbb5 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -1,8 +1,12 @@ import { QueryRunner } from "typeorm"; import { sectionTypeEnum } from "../../lib/src/index.js"; -import { env } from "./config/server.js"; import { Course, Section, Timetable } from "./entity/entities.js"; -import { addTimetable, removeTimetable } from "./utils/search.js"; +import { + addCourse, + addTimetable, + removeCourse, + removeTimetable, +} from "./utils/search.js"; interface ExamJSON { midsem: string | null; @@ -336,26 +340,7 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${oldCourseCount} old courses found`); for (const { id } of oldCourseIds) { - try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/remove`; - const res = await fetch(searchServiceURL, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ id }), - }); - if (!res.ok) { - const resJson = await res.json(); - console.log( - `error while removing course ${id} from search service: ${resJson.error}`, - ); - } - } catch (err: any) { - console.log( - `error while removing course ${id} from search service: ${err.message}`, - ); - } + removeCourse(id, console); } console.log("removed old courses from search service!"); @@ -373,27 +358,8 @@ export const ingestJSON = async ( .from(Course, "course") .leftJoinAndSelect("course.sections", "section") .where("course.id = :id", { id: id }) - .getOne(); - try { - const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/add`; - const res = await fetch(searchServiceURL, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(course), - }); - if (!res.ok) { - const resJson = await res.json(); - console.log( - `error while adding course ${id} to search service: ${resJson.error}`, - ); - } - } catch (err: any) { - console.log( - `error while adding course ${id} to search service: ${err.message}`, - ); - } + .getOneOrFail(); + addCourse(course, console); } console.log("added updated courses to search service!"); diff --git a/backend/src/utils/search.ts b/backend/src/utils/search.ts index a02496ab..ae1cca73 100644 --- a/backend/src/utils/search.ts +++ b/backend/src/utils/search.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import { Logger } from "pino"; import { env } from "../config/server.js"; -import { Timetable } from "../entity/entities.js"; +import { Course, Timetable } from "../entity/entities.js"; import { userRepository } from "../repositories/userRepository.js"; import sqids from "./sqids.js"; @@ -79,3 +79,58 @@ export const removeTimetable = async ( throw err; } }; + +export const addCourse = async (course: Course, logger: Logger | Console) => { + try { + const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/add`; + const res = await fetch(searchServiceURL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(course), + }); + if (!res.ok) { + const resJson = await res.json(); + logger.error( + `Error while adding course ${course.id} to search service: ${resJson.error}`, + ); + } + } catch (err: any) { + logger.error( + `Error while adding course ${course.id} to search service: ${ + "message" in err ? err.message : err + }`, + ); + throw err; + } +}; + +export const removeCourse = async ( + courseId: string, + logger: Logger | Console, +) => { + try { + const searchServiceURL = `${env.SEARCH_SERVICE_URL}/course/remove`; + const res = await fetch(searchServiceURL, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ id: courseId }), + }); + if (!res.ok) { + const resJson = await res.json(); + logger.error( + `Error while removing course ${courseId} from search service: ${resJson.error}`, + ); + } + } catch (err: any) { + logger.error( + `Error while removing course ${courseId} from search service: ${ + "message" in err ? err.message : err + }`, + ); + throw err; + } +}; From 823f38194f7d4bbc1de3fff3f7ef42cdd5bd75cf Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 23:21:05 +0530 Subject: [PATCH 09/11] refactor: clean up code --- .../timetable/editTimetableMetadata.ts | 15 ++++++--------- .../timetable/updateChangedTimetable.ts | 5 ----- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/backend/src/controllers/timetable/editTimetableMetadata.ts b/backend/src/controllers/timetable/editTimetableMetadata.ts index 171b5721..dfb9eb0c 100644 --- a/backend/src/controllers/timetable/editTimetableMetadata.ts +++ b/backend/src/controllers/timetable/editTimetableMetadata.ts @@ -117,18 +117,15 @@ export const editTimetableMetadata = async (req: Request, res: Response) => { return res.status(500).json({ message: "Internal Server Error" }); } - if (isDraft === false && isPrivate === false) { - try { + // update search service + try { + if (isDraft === false && isPrivate === false) { addTimetable(updatedTimetable, req.session?.email ?? "", logger); - } catch (err: any) { - return res.status(500).json({ message: "Internal Server Error" }); - } - } else { - try { + } else { removeTimetable(timetable.id, logger); - } catch (err: any) { - return res.status(500).json({ message: "Internal Server Error" }); } + } catch (err: any) { + return res.status(500).json({ message: "Internal Server Error" }); } return res.json({ message: "timetable edited" }); diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index a6c25b6e..98a161ff 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -240,11 +240,6 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { // update course in search service try { removeCourse(course.id, logger); - } catch (err: any) { - return res.status(500).json({ message: "Internal Server Error" }); - } - - try { addCourse(course, logger); } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); From 14af67bc5e389ae1295d2581263448c521659959 Mon Sep 17 00:00:00 2001 From: skoriop Date: Fri, 26 Jul 2024 23:41:57 +0530 Subject: [PATCH 10/11] perf: fix textbook N + 1 problem --- backend/src/ingestJSON.ts | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index fe0ffbb5..291963f7 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -345,20 +345,14 @@ export const ingestJSON = async ( console.log("removed old courses from search service!"); console.log("adding updated courses into search service..."); - const [updatedCourseIds, updatedCourseCount] = await queryRunner.manager + const [updatedCourses, updatedCourseCount] = await queryRunner.manager .createQueryBuilder() - .select("course.id") + .select("course") .from(Course, "course") + .leftJoinAndSelect("course.sections", "section") .getManyAndCount(); console.log(`${updatedCourseCount} courses found`); - for (const { id } of updatedCourseIds) { - const course = await queryRunner.manager - .createQueryBuilder() - .select("course") - .from(Course, "course") - .leftJoinAndSelect("course.sections", "section") - .where("course.id = :id", { id: id }) - .getOneOrFail(); + for (const course of updatedCourses) { addCourse(course, console); } console.log("added updated courses to search service!"); @@ -366,20 +360,14 @@ export const ingestJSON = async ( console.log("updating timetables in search service..."); const [timetableIds, timetableCount] = await queryRunner.manager .createQueryBuilder() - .select("timetable.id") + .select("timetable") .from(Timetable, "timetable") + .leftJoinAndSelect("timetable.sections", "section") .where("timetable.archived = :archived", { archived: true }) .getManyAndCount(); console.log(`${timetableCount} timetables are to be updated`); - for (const { id } of timetableIds) { - removeTimetable(id, console); - const timetable = await queryRunner.manager - .createQueryBuilder() - .select("timetable") - .from(Timetable, "timetable") - .leftJoinAndSelect("timetable.sections", "section") - .where("timetable.id = :id", { id }) - .getOneOrFail(); + for (const timetable of timetableIds) { + removeTimetable(timetable.id, console); addTimetable(timetable, null, console); } console.log("updated timetables in search service!"); From b701a7ceda667385f34f6aa5f9d85a4b209a8417 Mon Sep 17 00:00:00 2001 From: skoriop Date: Mon, 29 Jul 2024 16:14:43 +0530 Subject: [PATCH 11/11] fix: promises should be awaited man, just man --- backend/src/controllers/timetable/deleteTimetable.ts | 2 +- .../src/controllers/timetable/editTimetableMetadata.ts | 4 ++-- .../src/controllers/timetable/updateChangedTimetable.ts | 8 ++++---- backend/src/ingestJSON.ts | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/controllers/timetable/deleteTimetable.ts b/backend/src/controllers/timetable/deleteTimetable.ts index a3e82361..314e27e7 100644 --- a/backend/src/controllers/timetable/deleteTimetable.ts +++ b/backend/src/controllers/timetable/deleteTimetable.ts @@ -74,7 +74,7 @@ export const deleteTimetable = async (req: Request, res: Response) => { res.status(500).json({ message: "Internal Server Error" }); } try { - removeTimetable(timetable.id, logger); + await removeTimetable(timetable.id, logger); } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); } diff --git a/backend/src/controllers/timetable/editTimetableMetadata.ts b/backend/src/controllers/timetable/editTimetableMetadata.ts index dfb9eb0c..28001258 100644 --- a/backend/src/controllers/timetable/editTimetableMetadata.ts +++ b/backend/src/controllers/timetable/editTimetableMetadata.ts @@ -120,9 +120,9 @@ export const editTimetableMetadata = async (req: Request, res: Response) => { // update search service try { if (isDraft === false && isPrivate === false) { - addTimetable(updatedTimetable, req.session?.email ?? "", logger); + await addTimetable(updatedTimetable, req.session?.email ?? "", logger); } else { - removeTimetable(timetable.id, logger); + await removeTimetable(timetable.id, logger); } } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); diff --git a/backend/src/controllers/timetable/updateChangedTimetable.ts b/backend/src/controllers/timetable/updateChangedTimetable.ts index 98a161ff..7be1fa9e 100644 --- a/backend/src/controllers/timetable/updateChangedTimetable.ts +++ b/backend/src/controllers/timetable/updateChangedTimetable.ts @@ -239,8 +239,8 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { // update course in search service try { - removeCourse(course.id, logger); - addCourse(course, logger); + await removeCourse(course.id, logger); + await addCourse(course, logger); } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); } @@ -248,7 +248,7 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { // update timetables in search service for (const timetable of timetables) { try { - removeTimetable(timetable.id, logger); + await removeTimetable(timetable.id, logger); } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); } @@ -259,7 +259,7 @@ export const updateChangedTimetable = async (req: Request, res: Response) => { .where("timetable.id = :id", { id: timetable.id }) .getOneOrFail(); try { - addTimetable(timetableWithSections, null, logger); + await addTimetable(timetableWithSections, null, logger); } catch (err: any) { return res.status(500).json({ message: "Internal Server Error" }); } diff --git a/backend/src/ingestJSON.ts b/backend/src/ingestJSON.ts index 291963f7..84b24db4 100644 --- a/backend/src/ingestJSON.ts +++ b/backend/src/ingestJSON.ts @@ -340,7 +340,7 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${oldCourseCount} old courses found`); for (const { id } of oldCourseIds) { - removeCourse(id, console); + await removeCourse(id, console); } console.log("removed old courses from search service!"); @@ -353,7 +353,7 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${updatedCourseCount} courses found`); for (const course of updatedCourses) { - addCourse(course, console); + await addCourse(course, console); } console.log("added updated courses to search service!"); @@ -367,8 +367,8 @@ export const ingestJSON = async ( .getManyAndCount(); console.log(`${timetableCount} timetables are to be updated`); for (const timetable of timetableIds) { - removeTimetable(timetable.id, console); - addTimetable(timetable, null, console); + await removeTimetable(timetable.id, console); + await addTimetable(timetable, null, console); } console.log("updated timetables in search service!");