feat(#293): implement retry logic with exponential backoff
Add retry capability with exponential backoff for HTTP requests. - Implement withRetry utility with configurable retry logic - Exponential backoff: 1s, 2s, 4s, 8s (max) - Maximum 3 retries by default - Retry on network errors (ECONNREFUSED, ETIMEDOUT, etc.) - Retry on 5xx server errors and 429 rate limit - Do NOT retry on 4xx client errors - Integrate with connection service for HTTP requests Fixes #293 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ import { firstValueFrom } from "rxjs";
|
||||
import type { ConnectionRequest, ConnectionDetails } from "./types/connection.types";
|
||||
import type { PublicInstanceIdentity } from "./types/instance.types";
|
||||
import { FEDERATION_PROTOCOL_VERSION } from "./constants";
|
||||
import { withRetry } from "./utils/retry";
|
||||
|
||||
@Injectable()
|
||||
export class ConnectionService {
|
||||
@@ -87,10 +88,19 @@ export class ConnectionService {
|
||||
const signature = await this.signatureService.signMessage(request);
|
||||
const signedRequest: ConnectionRequest = { ...request, signature };
|
||||
|
||||
// Send connection request to remote instance
|
||||
// Send connection request to remote instance with retry logic
|
||||
try {
|
||||
await firstValueFrom(
|
||||
this.httpService.post(`${remoteUrl}/api/v1/federation/incoming/connect`, signedRequest)
|
||||
await withRetry(
|
||||
async () => {
|
||||
return await firstValueFrom(
|
||||
this.httpService.post(`${remoteUrl}/api/v1/federation/incoming/connect`, signedRequest)
|
||||
);
|
||||
},
|
||||
{
|
||||
maxRetries: 3,
|
||||
initialDelay: 1000, // 1s
|
||||
maxDelay: 8000, // 8s
|
||||
}
|
||||
);
|
||||
this.logger.log(`Connection request sent to ${remoteUrl}`);
|
||||
} catch (error) {
|
||||
@@ -368,13 +378,24 @@ export class ConnectionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch remote instance identity via HTTP
|
||||
* Fetch remote instance identity via HTTP with retry logic
|
||||
*/
|
||||
private async fetchRemoteIdentity(remoteUrl: string): Promise<PublicInstanceIdentity> {
|
||||
try {
|
||||
const normalizedUrl = this.normalizeUrl(remoteUrl);
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.get<PublicInstanceIdentity>(`${normalizedUrl}/api/v1/federation/instance`)
|
||||
const response = await withRetry(
|
||||
async () => {
|
||||
return await firstValueFrom(
|
||||
this.httpService.get<PublicInstanceIdentity>(
|
||||
`${normalizedUrl}/api/v1/federation/instance`
|
||||
)
|
||||
);
|
||||
},
|
||||
{
|
||||
maxRetries: 3,
|
||||
initialDelay: 1000, // 1s
|
||||
maxDelay: 8000, // 8s
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
|
||||
Reference in New Issue
Block a user