Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions server/src/module/ats/__tests__/ats.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,12 @@ function mockCacheMiss() {

function mockValidPdf(text = VALID_RESUME_TEXT) {
vi.mocked(PDFParse).mockImplementation(
() =>
({
function () {
return {
getText: vi.fn().mockResolvedValue({ text }),
destroy: vi.fn().mockResolvedValue(undefined),
}) as any,
} as any;
}
);
}

Expand Down Expand Up @@ -183,11 +184,12 @@ describe("AtsService", () => {
mockUserOwnsResume();
mockCacheMiss();
vi.mocked(PDFParse).mockImplementation(
() =>
({
function () {
return {
getText: vi.fn().mockResolvedValue({ text: "too short" }),
destroy: vi.fn().mockResolvedValue(undefined),
}) as any,
} as any;
}
);

await expect(
Expand Down Expand Up @@ -466,11 +468,12 @@ describe("AtsService", () => {
it("throws when PDF text extraction yields insufficient content", async () => {
mockUserOwnsResume();
vi.mocked(PDFParse).mockImplementation(
() =>
({
function () {
return {
getText: vi.fn().mockResolvedValue({ text: "tiny" }),
destroy: vi.fn().mockResolvedValue(undefined),
}) as any,
} as any;
}
);

await expect(
Expand Down
20 changes: 19 additions & 1 deletion server/src/module/professor/professor.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { prisma } from "../../database/db.js";
import { cacheGet, cacheSet } from "../../utils/cache.js";
import { cacheGet, cacheSet, cacheDelPattern } from "../../utils/cache.js";

const PROF_TTL = 3600;

Expand Down Expand Up @@ -106,5 +106,23 @@ export class ProfessorService {
await cacheSet(cacheKey, result, PROF_TTL);
return result;
}

async create(data: any) {
const record = await prisma.iitProfessor.create({ data });
await cacheDelPattern("professors:");
return record;
}

async update(id: number, data: any) {
const record = await prisma.iitProfessor.update({ where: { id }, data });
await cacheDelPattern("professors:");
return record;
}

async delete(id: number) {
const record = await prisma.iitProfessor.delete({ where: { id } });
await cacheDelPattern("professors:");
return record;
Comment on lines +110 to +125
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not surface mutation failure after the DB write has already committed.

On Line 111/117/123 the write completes before Line 112/118/124 invalidates cache. If cacheDelPattern fails, the method throws even though data is already persisted, which can cause retry-driven duplicate creates and integration inconsistency.

💡 Suggested fix
 export class ProfessorService {
+  private async invalidateProfessorCacheSafely() {
+    try {
+      await cacheDelPattern("professors:");
+    } catch (error) {
+      // Keep write-path successful; log and recover asynchronously if needed.
+      console.error("Professor cache invalidation failed", error);
+    }
+  }
+
   async create(data: any) {
     const record = await prisma.iitProfessor.create({ data });
-    await cacheDelPattern("professors:");
+    await this.invalidateProfessorCacheSafely();
     return record;
   }

   async update(id: number, data: any) {
     const record = await prisma.iitProfessor.update({ where: { id }, data });
-    await cacheDelPattern("professors:");
+    await this.invalidateProfessorCacheSafely();
     return record;
   }

   async delete(id: number) {
     const record = await prisma.iitProfessor.delete({ where: { id } });
-    await cacheDelPattern("professors:");
+    await this.invalidateProfessorCacheSafely();
     return record;
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async create(data: any) {
const record = await prisma.iitProfessor.create({ data });
await cacheDelPattern("professors:");
return record;
}
async update(id: number, data: any) {
const record = await prisma.iitProfessor.update({ where: { id }, data });
await cacheDelPattern("professors:");
return record;
}
async delete(id: number) {
const record = await prisma.iitProfessor.delete({ where: { id } });
await cacheDelPattern("professors:");
return record;
private async invalidateProfessorCacheSafely() {
try {
await cacheDelPattern("professors:");
} catch (error) {
// Keep write-path successful; log and recover asynchronously if needed.
console.error("Professor cache invalidation failed", error);
}
}
async create(data: any) {
const record = await prisma.iitProfessor.create({ data });
await this.invalidateProfessorCacheSafely();
return record;
}
async update(id: number, data: any) {
const record = await prisma.iitProfessor.update({ where: { id }, data });
await this.invalidateProfessorCacheSafely();
return record;
}
async delete(id: number) {
const record = await prisma.iitProfessor.delete({ where: { id } });
await this.invalidateProfessorCacheSafely();
return record;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/src/module/professor/professor.service.ts` around lines 110 - 125, The
create/update/delete methods call prisma.iitProfessor.* and then await
cacheDelPattern("professors:"), which risks throwing after the DB commit; change
the cache invalidation to be non-fatal: call cacheDelPattern asynchronously and
handle its errors without bubbling them (e.g., fire-and-forget or wrap in
try/catch and only log failures) so that failures to delete cache never roll
back or surface after the DB write. Update the create, update, and delete
functions (references: create, update, delete methods and cacheDelPattern) to
ensure the DB operation result is returned even if cache invalidation fails.

}
}

Loading