(
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;
},
)
| 5146 | ); |
| 5147 | |
| 5148 | const connectionCheckHealth = ( |
| 5149 | ref: ConnectionRef, |
| 5150 | options?: { |
| 5151 | /** Skip the probe and return the persisted verdict when it is younger |
| 5152 | * than this. The server owns the freshness decision so N open tabs |
| 5153 | * revalidating on load cannot stampede an upstream. Omit = always |
| 5154 | * probe (the manual "Check now"). */ |
| 5155 | readonly ifStaleMs?: number; |
| 5156 | }, |
| 5157 | ): Effect.Effect< |
| 5158 | HealthCheckResult, |
| 5159 | ConnectionNotFoundError | IntegrationNotFoundError | StorageFailure |
| 5160 | > => |
| 5161 | Effect.gen(function* () { |
| 5162 | const connectionRow = yield* findConnectionRow(ref); |
| 5163 | if (!connectionRow) { |
| 5164 | return yield* new ConnectionNotFoundError({ |
| 5165 | owner: ref.owner, |
| 5166 | integration: ref.integration, |
| 5167 | name: ref.name, |
| 5168 | }); |
| 5169 | } |
| 5170 | // A recorded invalid_grant is the AS's standing verdict on this grant |
| 5171 | // (the refresh path's gate, applied to probing): a probe can still |
| 5172 | // pass on the access token's remaining lifetime, and persisting that |
| 5173 | // "healthy" would hide the required reconnect until the token finally |
| 5174 | // lapses — with read-time revalidation then trusting the lie forever. |
| 5175 | // Serve the dead-grant verdict and probe nothing; this covers the |
| 5176 | // manual "Check now" too. Only the reconnect mint, which rewrites |
| 5177 | // `provider_state` wholesale, re-opens probing. Nothing is written: |
| 5178 | // a buried `expired` verdict (e.g. a failing tool sync landing after |
| 5179 | // the recorder) is already re-derived on every read through |
| 5180 | // `presentedLastHealth`, so plain row reads agree with what this |
| 5181 | // serves — and a repair write here could observe a pre-reconnect |
| 5182 | // dead grant, pass the verdict CAS inside one SQLite `updated_at` |
| 5183 | // second, and stamp the OLD grant's expired verdict onto the freshly |
| 5184 | // reconnected row. |
| 5185 | // The verdict this check replaces, for the flip attributes on the |
| 5186 | // span (`previous_status` / `changed`). Read once, before any path |
| 5187 | // can write, so every exit annotates against the same baseline. |
| 5188 | const previous = presentedLastHealth(connectionRow); |
| 5189 | const reauthState = oauthReauthRequiredFromProviderState(connectionRow.provider_state); |
| 5190 | if (reauthState !== null) { |
| 5191 | const result = deadGrantVerdict(reauthState, connectionRow); |
| 5192 | yield* annotateHealthVerdict("dead_grant", result, previous); |
| 5193 | return result; |
| 5194 | } |
| 5195 | if (options?.ifStaleMs !== undefined) { |
| 5196 | const cached = Option.getOrNull(decodeLastHealth(connectionRow.last_health)); |
| 5197 | if (cached && Date.now() - cached.checkedAt < options.ifStaleMs) { |
| 5198 | yield* annotateHealthVerdict("cache", cached, previous); |
| 5199 | return cached; |
| 5200 | } |
| 5201 | } |
| 5202 | const integrationRow = yield* findIntegrationRow(ref.integration); |
| 5203 | if (!integrationRow) { |
| 5204 | return yield* new IntegrationNotFoundError({ slug: ref.integration }); |
| 5205 | } |
no test coverage detected