(
ref: ConnectionRef,
options?: {
/** Skip the probe and return the persisted verdict when it is younger
* than this. The server owns the freshness decision so N open tabs
* revalidating on load cannot stampede an upstream. Omit = always
* probe (the manual "Check now"). */
readonly ifStaleMs?: number;
},
)
| 4586 | ); |
| 4587 | |
| 4588 | const connectionCheckHealth = ( |
| 4589 | ref: ConnectionRef, |
| 4590 | options?: { |
| 4591 | /** Skip the probe and return the persisted verdict when it is younger |
| 4592 | * than this. The server owns the freshness decision so N open tabs |
| 4593 | * revalidating on load cannot stampede an upstream. Omit = always |
| 4594 | * probe (the manual "Check now"). */ |
| 4595 | readonly ifStaleMs?: number; |
| 4596 | }, |
| 4597 | ): Effect.Effect< |
| 4598 | HealthCheckResult, |
| 4599 | ConnectionNotFoundError | IntegrationNotFoundError | StorageFailure |
| 4600 | > => |
| 4601 | Effect.gen(function* () { |
| 4602 | const connectionRow = yield* findConnectionRow(ref); |
| 4603 | if (!connectionRow) { |
| 4604 | return yield* new ConnectionNotFoundError({ |
| 4605 | owner: ref.owner, |
| 4606 | integration: ref.integration, |
| 4607 | name: ref.name, |
| 4608 | }); |
| 4609 | } |
| 4610 | // A recorded invalid_grant is the AS's standing verdict on this grant |
| 4611 | // (the refresh path's gate, applied to probing): a probe can still |
| 4612 | // pass on the access token's remaining lifetime, and persisting that |
| 4613 | // "healthy" would hide the required reconnect until the token finally |
| 4614 | // lapses — with read-time revalidation then trusting the lie forever. |
| 4615 | // Serve the dead-grant verdict and probe nothing; this covers the |
| 4616 | // manual "Check now" too. Only the reconnect mint, which rewrites |
| 4617 | // `provider_state` wholesale, re-opens probing. Nothing is written: |
| 4618 | // a buried `expired` verdict (e.g. a failing tool sync landing after |
| 4619 | // the recorder) is already re-derived on every read through |
| 4620 | // `presentedLastHealth`, so plain row reads agree with what this |
| 4621 | // serves — and a repair write here could observe a pre-reconnect |
| 4622 | // dead grant, pass the verdict CAS inside one SQLite `updated_at` |
| 4623 | // second, and stamp the OLD grant's expired verdict onto the freshly |
| 4624 | // reconnected row. |
| 4625 | // The verdict this check replaces, for the flip attributes on the |
| 4626 | // span (`previous_status` / `changed`). Read once, before any path |
| 4627 | // can write, so every exit annotates against the same baseline. |
| 4628 | const previous = presentedLastHealth(connectionRow); |
| 4629 | const reauthState = oauthReauthRequiredFromProviderState(connectionRow.provider_state); |
| 4630 | if (reauthState !== null) { |
| 4631 | const result = deadGrantVerdict(reauthState, connectionRow); |
| 4632 | yield* annotateHealthVerdict("dead_grant", result, previous); |
| 4633 | return result; |
| 4634 | } |
| 4635 | if (options?.ifStaleMs !== undefined) { |
| 4636 | const cached = Option.getOrNull(decodeLastHealth(connectionRow.last_health)); |
| 4637 | if (cached && Date.now() - cached.checkedAt < options.ifStaleMs) { |
| 4638 | yield* annotateHealthVerdict("cache", cached, previous); |
| 4639 | return cached; |
| 4640 | } |
| 4641 | } |
| 4642 | const integrationRow = yield* findIntegrationRow(ref.integration); |
| 4643 | if (!integrationRow) { |
| 4644 | return yield* new IntegrationNotFoundError({ slug: ref.integration }); |
| 4645 | } |
no test coverage detected