(
row: ConnectionRow,
provider: CredentialProvider,
)
| 1656 | }); |
| 1657 | |
| 1658 | const refreshConnectionToken = ( |
| 1659 | row: ConnectionRow, |
| 1660 | provider: CredentialProvider, |
| 1661 | ): Effect.Effect<string | null, StorageFailure | CredentialResolutionError> => |
| 1662 | // Share a single refresh per connection so concurrent resolves of the same |
| 1663 | // connection all await one refresh-token grant (the AS rotates the refresh |
| 1664 | // token; parallel grants would race on a consumed token — v1's refresh |
| 1665 | // deferred-map). The gate is cleared once the refresh settles so a later |
| 1666 | // expiry can refresh again. |
| 1667 | Effect.gen(function* () { |
| 1668 | const key = connectionKey(row); |
| 1669 | const existing = refreshInFlight.get(key); |
| 1670 | if (existing) return yield* existing; |
| 1671 | // `Effect.cached` memoizes the grant onto a deferred: it runs once and |
| 1672 | // replays to every awaiter sharing this entry. |
| 1673 | const memoized = yield* Effect.cached(performTokenRefresh(row, provider)); |
| 1674 | const gated = memoized.pipe( |
| 1675 | Effect.ensuring(Effect.sync(() => refreshInFlight.delete(key))), |
| 1676 | ); |
| 1677 | // Re-check after building (a peer fiber may have registered first while |
| 1678 | // we built ours) so everyone converges on the same shared grant. |
| 1679 | const winner = refreshInFlight.get(key) ?? gated; |
| 1680 | if (winner === gated) refreshInFlight.set(key, gated); |
| 1681 | return yield* winner; |
| 1682 | }); |
| 1683 | |
| 1684 | // Resolve every named input of a connection (`variable → value`). A |
| 1685 | // single-secret connection yields `{ token: <value> }`; an apiKey method with |
no test coverage detected