@@ -315,6 +315,11 @@ export default class IntegrationService {
315315 async destroyAll ( ids ) {
316316 const toRemoveRepo = new Set < string > ( )
317317 let segmentId
318+ // Collect GitLab webhook info before opening the transaction so external HTTP calls
319+ // don't hold the DB connection idle long enough to trigger a connection timeout.
320+ const gitlabWebhookRemovals : Array < { token : string ; projectIds : number [ ] ; hookIds : number [ ] } > =
321+ [ ]
322+
318323 const transaction = await SequelizeRepository . createTransaction ( this . options )
319324
320325 try {
@@ -446,11 +451,11 @@ export default class IntegrationService {
446451 }
447452
448453 if ( integration . platform === PlatformType . GITLAB && integration . settings . webhooks ) {
449- await removeGitlabWebhooks (
450- integration . token ,
451- integration . settings . webhooks . map ( ( hook ) => hook . projectId ) ,
452- integration . settings . webhooks . map ( ( hook ) => hook . hookId ) ,
453- )
454+ gitlabWebhookRemovals . push ( {
455+ token : integration . token ,
456+ projectIds : integration . settings . webhooks . map ( ( hook ) => hook . projectId ) ,
457+ hookIds : integration . settings . webhooks . map ( ( hook ) => hook . hookId ) ,
458+ } )
454459 }
455460
456461 if ( integration . platform === PlatformType . GIT ) {
@@ -495,6 +500,14 @@ export default class IntegrationService {
495500 await SequelizeRepository . rollbackTransaction ( transaction )
496501 throw error
497502 }
503+
504+ // Remove GitLab webhooks after the transaction commits — these are external HTTP calls
505+ // and must not hold a DB connection open.
506+ await Promise . all (
507+ gitlabWebhookRemovals . map ( ( { token, projectIds, hookIds } ) =>
508+ removeGitlabWebhooks ( token , projectIds , hookIds ) ,
509+ ) ,
510+ )
498511 }
499512
500513 async findById ( id ) {
0 commit comments