* Mark connection as failed (internal use after failed probe)
(key: string, error: string)
| 423 | * Mark connection as failed (internal use after failed probe) |
| 424 | */ |
| 425 | private markFailedByKey(key: string, error: string): void { |
| 426 | const current = this.health.get(key); |
| 427 | const failures = (current?.consecutiveFailures ?? 0) + 1; |
| 428 | const backoffIndex = Math.min(failures - 1, SSH_BACKOFF_SCHEDULE_SECONDS.length - 1); |
| 429 | const backoffSecs = withSshBackoffJitter(SSH_BACKOFF_SCHEDULE_SECONDS[backoffIndex]); |
| 430 | |
| 431 | this.clearReadyControlPaths(key); |
| 432 | this.health.set(key, { |
| 433 | status: "unhealthy", |
| 434 | lastFailure: new Date(), |
| 435 | lastError: error, |
| 436 | backoffUntil: new Date(Date.now() + backoffSecs * 1000), |
| 437 | consecutiveFailures: failures, |
| 438 | }); |
| 439 | |
| 440 | log.warn( |
| 441 | `SSH connection failed (${failures} consecutive). Backoff for ${backoffSecs.toFixed(1)}s. Error: ${error}` |
| 442 | ); |
| 443 | } |
| 444 | |
| 445 | /** |
| 446 | * Clear all health state. Used in tests to reset between test cases |
no test coverage detected