Commit 15dbfd5
committed
fix(oauth): narrow async_auth_flow lock scope to avoid blocking long-poll requests
Previously the entire `OAuthClientProvider.async_auth_flow` body ran under
`self.context.lock`, including the `yield request` that hands the request
off to httpx. For requests that complete quickly this is fine, but a GET
SSE long-poll holds the lock for the full SSE lifetime — which means any
concurrent POST (e.g. `tools/call`) is blocked waiting for the lock,
producing a ~16s perceived stall on lazy MCP connections that use OAuth.
This commit splits the single coarse lock into purpose-specific scopes:
Phase 1 (context.lock): initialize state, capture protocol_version, and
decide whether a refresh is needed. Short-held; no HTTP I/O.
Phase 2 (refresh_lock, new): single-flight token refresh. The refresh
request `yield` happens outside any lock. A double-check inside
`context.lock` ensures concurrent waiters do not redundantly refresh
after another coroutine completed one.
Phase 3 (no lock): add the auth header and yield the actual request.
GET SSE long-polls and other long-running requests no longer block
unrelated traffic.
Phase 4 (context.lock): 401 / 403 full OAuth re-auth path. Conservatively
kept under lock because this path is rare and its yielded sub-requests
(metadata discovery, registration, token exchange) hit the AS, not the
resource server. A future refactor can narrow this further.
Lock additions:
- `OAuthContext.refresh_lock: anyio.Lock` provides single-flight refresh
so concurrent requests trigger at most one token refresh.
Behavior changes:
- Concurrent requests through the same `OAuthClientProvider` no longer
serialize at the lock. GET SSE long-polls and POSTs now proceed in
parallel.
- Token refresh remains serialized (via `refresh_lock`), preserving the
invariant that only one refresh request is in flight at a time.
- Public API and behavior are otherwise unchanged.
Related upstream issue:
#13261 parent f475344 commit 15dbfd5
1 file changed
Lines changed: 61 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
117 | 127 | | |
| 128 | + | |
118 | 129 | | |
119 | 130 | | |
120 | 131 | | |
| |||
504 | 515 | | |
505 | 516 | | |
506 | 517 | | |
507 | | - | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
508 | 529 | | |
509 | 530 | | |
510 | 531 | | |
| |||
513 | 534 | | |
514 | 535 | | |
515 | 536 | | |
516 | | - | |
517 | | - | |
518 | | - | |
519 | | - | |
520 | | - | |
521 | | - | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
527 | | - | |
528 | | - | |
529 | | - | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
530 | 574 | | |
531 | 575 | | |
532 | 576 | | |
| |||
619 | 663 | | |
620 | 664 | | |
621 | 665 | | |
622 | | - | |
| 666 | + | |
| 667 | + | |
623 | 668 | | |
624 | 669 | | |
625 | 670 | | |
| |||
0 commit comments