From 240ce2a6736b03da0d5b80468734b6215fcf635e Mon Sep 17 00:00:00 2001 From: enjoyandlove Date: Tue, 19 May 2026 10:12:50 -0400 Subject: [PATCH] fix(installation): replace find-then-insert with atomic upsert (#110) --- .../webhook/handlers/installation.handler.ts | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/das/src/webhook/handlers/installation.handler.ts b/packages/das/src/webhook/handlers/installation.handler.ts index 2638652..7eaf630 100644 --- a/packages/das/src/webhook/handlers/installation.handler.ts +++ b/packages/das/src/webhook/handlers/installation.handler.ts @@ -38,22 +38,19 @@ export class InstallationHandler { payload.repositories ?? payload.repositories_added ?? []; for (const repo of repos) { - // Check existence first so we only set added_at on insert, not on every - // re-fire of installation.created / installation_repositories.added. - const existing = await this.repoRepo.findOneBy({ - repoFullName: repo.full_name, - }); - if (existing) { - await this.repoRepo.update(repo.full_name, { - installationId: String(installationId), - }); - } else { - await this.repoRepo.insert({ + // Atomic upsert: insert with addedAt on first encounter; on conflict only + // update installationId so addedAt is never overwritten on re-fires. + await this.repoRepo + .createQueryBuilder() + .insert() + .into(Repo) + .values({ repoFullName: repo.full_name, installationId: String(installationId), addedAt: new Date().toISOString(), - }); - } + }) + .orUpdate(["installationId"], ["repoFullName"]) + .execute(); this.logger.log(`Tracking repo: ${repo.full_name}`); }