fix(#275): Prevent silent connection initiation failures
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

Fixed silent connection initiation failures where HTTP errors were caught
but success was returned to the user, leaving zombie connections in
PENDING state forever.

Changes:
- Delete failed connection from database when HTTP request fails
- Throw BadRequestException with clear error message
- Added test to verify connection deletion and exception throwing
- Import BadRequestException in connection.service.ts

User Impact:
- Users now receive immediate feedback when connection initiation fails
- No more zombie connections stuck in PENDING state
- Clear error messages indicate the reason for failure

Testing:
- Added test case: "should delete connection and throw error if request fails"
- All 21 connection service tests passing
- Quality gates: lint, typecheck, build all passing

Fixes #275

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 20:21:06 -06:00
parent 7a84d96d72
commit 7d9c102c6d
3 changed files with 125 additions and 2 deletions

View File

@@ -0,0 +1,82 @@
# Issue #275: Fix silent connection initiation failures
## Objective
Fix silent connection initiation failures where HTTP errors are caught but success is returned to the user, leaving zombie connections in PENDING state forever.
## Location
`apps/api/src/federation/connection.service.ts:72-80`
## Problem
Current code:
```typescript
try {
await firstValueFrom(
this.httpService.post(`${remoteUrl}/api/v1/federation/incoming/connect`, signedRequest)
);
this.logger.log(`Connection request sent to ${remoteUrl}`);
} catch (error) {
this.logger.error(`Failed to send connection request to ${remoteUrl}`, error);
// Connection is still created in PENDING state, can be retried
}
return this.mapToConnectionDetails(connection);
```
Issues:
- Catches HTTP failures but returns success
- Connection stays in PENDING state forever
- Creates zombie connections
- User sees success message but connection actually failed
## Solution
1. Delete the failed connection from database
2. Throw exception with clear error message
3. User gets immediate feedback that connection failed
## Implementation
```typescript
try {
await firstValueFrom(
this.httpService.post(`${remoteUrl}/api/v1/federation/incoming/connect`, signedRequest)
);
this.logger.log(`Connection request sent to ${remoteUrl}`);
} catch (error) {
this.logger.error(`Failed to send connection request to ${remoteUrl}`, error);
// Delete the failed connection to prevent zombie connections
await this.prisma.federationConnection.delete({
where: { id: connection.id },
});
throw new BadRequestException(
`Failed to initiate connection to ${remoteUrl}: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
```
## Testing
Test scenarios:
1. Remote instance is unreachable - should throw exception and delete connection
2. Remote instance returns error - should throw exception and delete connection
3. Remote instance times out - should throw exception and delete connection
4. Remote instance returns success - should create connection in PENDING state
## Progress
- [ ] Create scratchpad
- [ ] Implement fix in connection.service.ts
- [ ] Add/update tests
- [ ] Run quality gates
- [ ] Commit changes
- [ ] Create PR
- [ ] Merge to develop
- [ ] Close issue #275