The observation
This is the client-side sibling of #6682. On the client_secret (client credentials / ROPC) branch, every outbound RPC builds a fresh auth manager and discards the token it fetched:
get_auth_token constructs a new AuthenticationClientManagerFactory, manager, and OIDCDiscoveryService per call (sdk/python/feast/permissions/client/client_auth_token.py).
- All three interceptors invoke it per request: the gRPC interceptor on every intercepted call, the Arrow Flight middleware in
sending_headers, and the HTTP wrapper even on its cached-session path.
So each outbound request pays a discovery GET plus a token POST against the IdP, for a token that is typically valid for an hour. Measured with counting mocks on current master: 5 outbound calls perform 5 discovery GETs and 5 token POSTs.
Beyond the latency, a batch loop (e.g. many get_online_features calls against a remote server, or materialization against a remote registry) multiplies IdP load by request count, which can trip IdP rate limits.
Fix
Cache issued tokens keyed by the token-request identity (discovery URL, client id/secret, username, password) and reuse each until shortly before its expiry, read from the token's own exp claim with the token response's expires_in as a fallback. A token whose expiry cannot be determined is not cached, preserving today's per-call behavior for opaque tokens. The static-token, env-var, and mounted service-account sources are unaffected (they were already cheap).
After the change the same 5-call measurement performs 1 discovery GET and 1 token POST.
PR to follow shortly.
The observation
This is the client-side sibling of #6682. On the
client_secret(client credentials / ROPC) branch, every outbound RPC builds a fresh auth manager and discards the token it fetched:get_auth_tokenconstructs a newAuthenticationClientManagerFactory, manager, andOIDCDiscoveryServiceper call (sdk/python/feast/permissions/client/client_auth_token.py).sending_headers, and the HTTP wrapper even on its cached-session path.So each outbound request pays a discovery GET plus a token POST against the IdP, for a token that is typically valid for an hour. Measured with counting mocks on current master: 5 outbound calls perform 5 discovery GETs and 5 token POSTs.
Beyond the latency, a batch loop (e.g. many
get_online_featurescalls against a remote server, or materialization against a remote registry) multiplies IdP load by request count, which can trip IdP rate limits.Fix
Cache issued tokens keyed by the token-request identity (discovery URL, client id/secret, username, password) and reuse each until shortly before its expiry, read from the token's own
expclaim with the token response'sexpires_inas a fallback. A token whose expiry cannot be determined is not cached, preserving today's per-call behavior for opaque tokens. The static-token, env-var, and mounted service-account sources are unaffected (they were already cheap).After the change the same 5-call measurement performs 1 discovery GET and 1 token POST.
PR to follow shortly.