fix: address code quality issues in session pool, approval, and main

- session.ts: add onReconnect callback so reconnected socket replaces stale pool entry
- session-pool.ts: pass onReconnect to update pool on reconnect; add closeAll() to gracefully end WebSocket connections on shutdown
- approval.ts: use approved flag so double-approval race (updateMany count=0) returns null instead of sending duplicate forward jobs
- main.ts: wrap pool.add() in try/catch to continue if one account fails; replace silent groupMap fallback with explicit error log and early return; call pool.closeAll() before BullMQ shutdown to prevent hanging sockets
- Tests: add closeAll() test to session-pool.test.ts; add double-approval race test to approval.test.ts (56 tests total, all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 17:35:52 +05:30
parent 9e3ee0cd38
commit 41aabc4c0d
6 changed files with 82 additions and 5 deletions
+23
View File
@@ -76,6 +76,29 @@ describe('handleStarReaction', () => {
expect(await handleStarReaction(makeReaction(), adminJids, prisma)).toBeNull();
});
it('returns null on double-approval race (updateMany returns count=0)', async () => {
const prisma = {
message: {
findUnique: jest.fn().mockResolvedValue({
id: 'msg_1',
status: 'PENDING',
approval: null,
content: 'hello',
senderName: 'Alice',
sourceGroup: { name: 'UP Parivar Dallas', syncRoutesFrom: [] },
}),
},
$transaction: jest.fn().mockImplementation(async (fn: any) => fn({
message: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) },
approval: { create: jest.fn().mockResolvedValue({}) },
})),
} as any;
const result = await handleStarReaction(makeReaction(), adminJids, prisma);
expect(result).toBeNull();
expect(prisma.$transaction).toHaveBeenCalled();
});
it('approves message and returns empty array when no sync routes', async () => {
const prisma = {
message: {
+4
View File
@@ -30,12 +30,14 @@ export async function handleStarReaction(
if (message.status !== 'PENDING') return null;
if (message.approval) return null;
let approved = false;
await prisma.$transaction(async (tx: any) => {
const updated = await tx.message.updateMany({
where: { id: message.id, status: 'PENDING' },
data: { status: 'APPROVED' },
});
if (updated.count === 0) return; // another admin approved first — idempotent
approved = true;
await tx.approval.create({
data: {
messageId: message.id,
@@ -45,6 +47,8 @@ export async function handleStarReaction(
});
});
if (!approved) return null;
const jobs: ForwardJobData[] = message.sourceGroup.syncRoutesFrom
.filter((route: any) => route.targetGroup != null)
.map((route: any) => ({