fix: Scope cached http(s) agents more strongly#6716
Conversation
| ): HttpAgentConfig | HttpsAgentConfig { | ||
| const protocol = getProtocolOrDefault(destination); | ||
| const cacheKey = hashCacheKey({ protocol, options }); | ||
| const cacheKey = hashCacheKey({ destination, options }); |
There was a problem hiding this comment.
[Nit] destination.certificates and options already overlap — the same cert material ends up in the hash twice. Is there any functional impact on this change?
There was a problem hiding this comment.
Including the full destination busts the cache on every token refresh for OAuth2ClientCredentials/OAuth2SAMLBearerFlow destinations — `authTokens.value changes hourly but is never read by createAgent, so keep-alive reuse breaks entirely for those destinations.
There was a problem hiding this comment.
I would like to suggest scoping the key to only what affects agent behavior:
const cacheKey = hashCacheKey({
protocol,
options,
proxyConfiguration: destination.proxyConfiguration,
cloudConnectorLocationId: destination.cloudConnectorLocationId
});
There was a problem hiding this comment.
I think a 1h cache is acceptable for this use-case. In addition to cloudConnectorLocationId for the proxy the agent also needs to be keyed per-user.
InjunPark-sap
left a comment
There was a problem hiding this comment.
nit question and suggest changes on http-agent.ts:309
InjunPark-sap
left a comment
There was a problem hiding this comment.
Two open questions:
-
Does
authTokensactually appear in the destination object passed togetAgentConfigin OAuth2 flows? If yes, every token refresh produces a new cache key and keep-alive reuse is lost. -
Is
proxyConfigurationsufficient for per-user keying, or are there cases where the user identity affects agent behavior outside ofproxyConfiguration.headers?
|
InjunPark-sap
left a comment
There was a problem hiding this comment.
Approval with the understanding that OAuth2 destinations will see reduced agent reuse on token refresh. (Worth revisiting if it shows up as a connection overhead issue in production.)
| ): Promise<HttpAgentConfig | HttpsAgentConfig> { | ||
| const protocol = getProtocolOrDefault(destination); | ||
| const cacheKey = await hashCacheKey({ protocol, options }); | ||
| const cacheKey = await hashCacheKey({ destination, options }); |
There was a problem hiding this comment.
[req] I don't think it is a good idea to hash the whole destination. E.g. auth tokens would be part of the key. Consider using specific values from the destination, like name and auth type. Also, this will expire, right? So if the destination changes it will eventually be re-created?
There was a problem hiding this comment.
What do you think about special-casing for connectivity only? So far only for that destination there are additional requirements.
Regarding expiring the http agents should also eventually be evicted from the LRU cache.
I did choose the whole destination because connectivity service seems to be very sensitive to connection re-use: they need to be different both per-user and per-connectivity-location. Including the destination token allowed satisfying the per-user requirement. I will re-evaluate the options, and whether to just default to keepAlive: false for the connectivity proxy.
There was a problem hiding this comment.
What do you think about special-casing for connectivity only? So far only for that destination there are additional requirements.
That might make it more complex.
I did choose the whole destination because connectivity service seems to be very sensitive to connection re-use: they need to be different both per-user and per-connectivity-location. Including the destination token allowed satisfying the per-user requirement. I will re-evaluate the options, and whether to just default to
keepAlive: falsefor the connectivity proxy.
Would it work to just include user and connectivity information (without secrets) for the key?
There was a problem hiding this comment.
I don't have an E2E test setup, but as currently implemented for connectivity this PR extracts user/tenant information and the location Id into the identifier.
There was a problem hiding this comment.
Currently it has to be connectivity specific (SAP-Connectivity-Authentication), but I could also try to extend this to extract the data from other JWT locations.
…http-agent-cache * origin/main: (33 commits) fix(openapi): Return `Blob` instead of `Buffer` (matching external types) (#6663) chore(deps): bump fast-xml-parser from 5.9.3 to 5.10.0 (#6780) chore: merge dependabot dev and prod config (#6779) chore: fix dependabot config (#6778) chore: add dev dependency config (#6777) chore(deps-dev): bump turbo from 2.10.0 to 2.10.4 (#6758) chore(deps): bump typescript-eslint from 8.62.1 to 8.63.0 (#6774) chore(deps-dev): bump @sap/cds-dk from 10.0.3 to 10.0.4 (#6772) chore(deps): bump memfs from 4.57.8 to 4.64.0 (#6769) chore(deps): bump @typescript-eslint/parser from 8.62.1 to 8.63.0 (#6776) chore(deps-dev): bump @eslint/eslintrc from 3.3.5 to 3.3.6 (#6773) chore(deps): bump prettier from 3.9.4 to 3.9.5 (#6771) chore(deps-dev): bump eslint from 10.6.0 to 10.7.0 (#6768) chore(deps): bump content-type and @types/content-type (#6608) feat(deps): bump eslint-plugin-jsdoc from 63.0.10 to 63.0.13 (#6751) feat(deps-dev): bump typedoc from 0.28.19 to 0.28.20 (#6752) feat(deps-dev): bump @types/node from 22.20.0 to 22.20.1 (#6756) feat(deps): bump the codeql group across 1 directory with 3 updates (#6763) chore: Remove devEngines constraint again (#6760) chore: Only allow single pnpm version for dependabot (corepack) (#6761) ...
a29f4ef to
41b51e9
Compare
Closes https://github.com/SAP/ai-sdk-js-backlog/issues/604.