(
row: ConnectionRow,
provider: CredentialProvider,
trigger: RefreshTrigger = "proactive",
)
| 2759 | ); |
| 2760 | |
| 2761 | const refreshConnectionToken = ( |
| 2762 | row: ConnectionRow, |
| 2763 | provider: CredentialProvider, |
| 2764 | trigger: RefreshTrigger = "proactive", |
| 2765 | ): Effect.Effect<string | null, StorageFailure | CredentialResolutionError> => |
| 2766 | // Share a single refresh per connection so concurrent resolves of the same |
| 2767 | // connection all await one refresh-token grant (the AS rotates the refresh |
| 2768 | // token; parallel grants would race on a consumed token — v1's refresh |
| 2769 | // deferred-map). The gate is cleared once the refresh settles so a later |
| 2770 | // expiry can refresh again. |
| 2771 | Effect.suspend(() => { |
| 2772 | const key = connectionKey(row); |
| 2773 | // Joining an in-flight grant is correct for BOTH triggers: whatever |
| 2774 | // that peer mints is newer than the token this fiber just saw rejected, |
| 2775 | // which is exactly what a reactive retry wants. The gate is cleared on |
| 2776 | // settle, so a 401 arriving after a refresh completed starts a fresh |
| 2777 | // grant rather than replaying a stale result. |
| 2778 | const existing = refreshInFlight.get(key); |
| 2779 | if (existing) return Deferred.await(existing); |
| 2780 | |
| 2781 | // The grant runs on a DETACHED fiber and every caller — including this |
| 2782 | // one — only awaits its deferred. The entry is shared across execution |
| 2783 | // stacks, so the fiber that registers it is merely the first arrival, |
| 2784 | // not an owner. Running the grant ON that fiber would hand it that |
| 2785 | // caller's interruption: a disconnected MCP client, an execution |
| 2786 | // deadline or a cancelled tool call would fail every peer awaiting the |
| 2787 | // same entry with an interrupt none of them caused and none can act on. |
| 2788 | // Awaiting is per-caller, so a cancelled peer detaches without touching |
| 2789 | // the grant or its siblings, and a grant nobody is left waiting on |
| 2790 | // still settles and still persists the rotated token — which is what |
| 2791 | // keeps the next caller off a consumed one. Token requests are bounded |
| 2792 | // by `AbortSignal.timeout`, so the detached fiber cannot outlive its |
| 2793 | // request. |
| 2794 | const deferred = Deferred.makeUnsafe< |
| 2795 | string | null, |
| 2796 | StorageFailure | CredentialResolutionError |
| 2797 | >(); |
| 2798 | // Nothing suspends between the lookup above and this registration, so |
| 2799 | // check-and-set is atomic against peer fibers and cannot double-fire. |
| 2800 | refreshInFlight.set(key, deferred); |
| 2801 | const run = performTokenRefresh(row, provider, trigger).pipe( |
| 2802 | Effect.exit, |
| 2803 | Effect.flatMap((exit) => Deferred.done(deferred, exit)), |
| 2804 | Effect.ensuring(Effect.sync(() => void refreshInFlight.delete(key))), |
| 2805 | ); |
| 2806 | return Effect.forkDetach(run).pipe(Effect.andThen(Deferred.await(deferred))); |
| 2807 | }); |
| 2808 | |
| 2809 | // Resolve every named input of a connection (`variable → value`). A |
| 2810 | // single-secret connection yields `{ token: <value> }`; an apiKey method with |
no test coverage detected