1 Commits

Author SHA1 Message Date
Hyeonsang Cho
161c3503d0
fix(github): build the App JWT off the loop and reuse the parsed key (#8203)
* fix(github): build the App JWT off the loop and reuse the parsed key

mint_installation_token() runs on the channel manager's event loop. On
every cold or expiring installation token it built the App JWT inline:
it read GITHUB_APP_PRIVATE_KEY_PATH and passed the PEM to jwt.encode,
which parses and validates the RSA key each time. For RSA-2048 the parse
is ~45 ms of the ~50 ms loop stall, and it holds the GIL, so a worker
thread alone does not help.

Reuse the parsed key while the PEM text is unchanged (still read on
every mint, so rotation needs no restart; parsed through PyJWT's own
RS256 prepare_key, so formats and errors are unchanged; failures are not
cached), and build the JWT in asyncio.to_thread so the file read and the
signature leave the loop. Later mints drop from ~48 ms to ~1.4 ms of
loop stall.

* test(github): pin the single parse under concurrent mints

Async mints call mint_app_jwt in worker threads, and the lock around the
parsed-key cache is what keeps a cold race from parsing the key twice.
Two threads now start mint_app_jwt behind a barrier while the first
parse is held open; the key must be parsed once.

The test-only reset also takes the lock, so a mint still parsing in a
worker thread finishes before the reset instead of storing its key after
it.
2026-11-13 14:31:29 +08:00