From 4dce71a1fe22774391bf0d0e87f1564c3b93b496 Mon Sep 17 00:00:00 2001 From: Dries Augustyns Date: Sat, 3 Jan 2026 11:40:27 +0100 Subject: [PATCH] fix: Reentry into segment not working after exit --- apps/api/src/services/SegmentService.ts | 40 +++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/apps/api/src/services/SegmentService.ts b/apps/api/src/services/SegmentService.ts index d246a68..301ef4e 100644 --- a/apps/api/src/services/SegmentService.ts +++ b/apps/api/src/services/SegmentService.ts @@ -356,15 +356,43 @@ export class SegmentService { for (let i = 0; i < toAdd.length; i += ADD_BATCH_SIZE) { const batch = toAdd.slice(i, i + ADD_BATCH_SIZE); - await prisma.segmentMembership.createMany({ - data: batch.map(contactId => ({ + // Check which contacts already have a membership record (inactive) + const existingMemberships = await prisma.segmentMembership.findMany({ + where: { segmentId, - contactId, - enteredAt: new Date(), - })), - skipDuplicates: true, + contactId: {in: batch}, + }, + select: {contactId: true}, }); + const existingContactIds = new Set(existingMemberships.map(m => m.contactId)); + const newEntries = batch.filter(id => !existingContactIds.has(id)); + const reEntries = batch.filter(id => existingContactIds.has(id)); + + if (newEntries.length > 0) { + await prisma.segmentMembership.createMany({ + data: newEntries.map(contactId => ({ + segmentId, + contactId, + enteredAt: new Date(), + })), + skipDuplicates: true, + }); + } + + if (reEntries.length > 0) { + await prisma.segmentMembership.updateMany({ + where: { + segmentId, + contactId: {in: reEntries}, + }, + data: { + exitedAt: null, + enteredAt: new Date(), + }, + }); + } + // Create segment-specific entry events for each contact in the batch for (const contactId of batch) { try {