feat: Improve handling of HTTP/HTTPS agent sessions#6498
feat: Improve handling of HTTP/HTTPS agent sessions#6498davidkna-sap wants to merge 15 commits intomainfrom
Conversation
a1f20f3 to
68fd5d8
Compare
Co-authored-by: David Knaack <[email protected]>
ZhongpinWang
left a comment
There was a problem hiding this comment.
Overall very nice implementation. 👍 I love the idea of making our cache a LRU cache. Btw we also have an async cache, not sure if that one needs to be changed as well. Otherwise, some small suggestions.
| @@ -82,10 +102,41 @@ export class Cache<T> implements CacheInterface<T> { | |||
| * @param item - The entry to cache. | |||
| */ | |||
| set(key: string | undefined, item: CacheEntry<T>): void { | |||
There was a problem hiding this comment.
[q] In general, I wonder why this key can be undefined :)
There was a problem hiding this comment.
Claude is claiming it's for the benefit of getDestinationCacheKey
| * Object that stores all cached entries. | ||
| */ | ||
| private cache: Record<string, CacheEntry<T>>; | ||
| private cache: Map<string, CacheEntry<T>>; |
There was a problem hiding this comment.
Nice 👍 Map maintains the insertion order.
| * @returns A hash of the given value using a cryptographic hash function. | ||
| */ | ||
| export function hashCacheKey(value: Record<string, unknown>): string { | ||
| const serialized = JSON.stringify(value); |
There was a problem hiding this comment.
Have you checked if this is sufficient? JSON.stringify cannot stringify many things like Map or Set etc.
Maybe check alternatives https://www.npmjs.com/package/fast-json-stable-stringify or something else.
There was a problem hiding this comment.
I switched to ohash (v1 instead of v2 for CJS support, v1 is still getting updates), Map/Set wouldn't be an issue here, but the values can contain functions.
I can switch to JSON.stringify's replacer option to handle functions if you prefer that, as TS is also having some issues with ohash in general.
There was a problem hiding this comment.
I also did some search, but tbh none of them seems to be very actively maintained. Maybe they just work without problem.
Also maybe we can try require() now since node 20 is (very soon) EOL
cdf9b3a to
e535ea9
Compare
e535ea9 to
002f644
Compare
marikaner
left a comment
There was a problem hiding this comment.
Didn't get through everything yet. Seems like an improvement 😊
| const entry = key ? this.cache.get(key) : undefined; | ||
| if (entry) { | ||
| if (isExpired(entry)) { | ||
| this.cache.delete(key!); | ||
| return undefined; | ||
| } | ||
| // LRU cache: Move accessed entry to the end of the Map to mark it as recently used | ||
| if (this.maxSize !== Infinity) { | ||
| this.cache.delete(key!); | ||
| this.cache.set(key!, entry); | ||
| } | ||
| } | ||
| return entry?.entry; |
There was a problem hiding this comment.
[pp]
| const entry = key ? this.cache.get(key) : undefined; | |
| if (entry) { | |
| if (isExpired(entry)) { | |
| this.cache.delete(key!); | |
| return undefined; | |
| } | |
| // LRU cache: Move accessed entry to the end of the Map to mark it as recently used | |
| if (this.maxSize !== Infinity) { | |
| this.cache.delete(key!); | |
| this.cache.set(key!, entry); | |
| } | |
| } | |
| return entry?.entry; | |
| if (key) { | |
| const entry = this.cache.get(key); | |
| if (isExpired(entry)) { | |
| this.cache.delete(key!); | |
| return undefined; | |
| } | |
| // LRU cache: Move accessed entry to the end of the Map to mark it as recently used | |
| if (this.maxSize !== Infinity) { | |
| this.cache.delete(key); | |
| this.cache.set(key, entry); | |
| } | |
| return entry.entry; | |
| } |
There was a problem hiding this comment.
Handled this differently because this.cache.get(key); can return undefined.
Co-authored-by: Marika Marszalkowski <[email protected]> Co-authored-by: David Knaack <[email protected]>
* origin/main: (27 commits) chore: Replace mock-fs with memfs/unionfs for fs mocking (#6470) chore(deps-dev): bump @changesets/cli from 2.30.0 to 2.31.0 (#6515) chore(deps): bump bignumber.js from 10.0.2 to 11.0.0 (#6511) chore(deps): bump @changesets/get-release-plan from 4.0.15 to 4.0.16 (#6518) chore(check-public-api): Use tempdir instead of mockfs (#6468) chore(deps): bump prettier from 3.8.2 to 3.8.3 (#6510) chore: Refactor test imports to use @sap-cloud-sdk/test-util-internal pkg (#6467) chore: Add license-checker action for pnpm (#6473) chore(deps): bump follow-redirects from 1.15.11 to 1.16.0 (#6495) chore: Add composite setup action for pnpm (#6507) fix: Avoid caching jwt if it needs to be forwarded (#6007) Change status from proposed to decided chore(deps): bump typescript-eslint from 8.58.1 to 8.58.2 (#6514) chore(deps): bump @typescript-eslint/parser from 8.58.1 to 8.58.2 (#6513) chore(deps-dev): bump @sap/cds-dk from 9.8.3 to 9.8.4 (#6512) chore(deps): bump fast-xml-parser from 5.5.11 to 5.6.0 (#6509) chore(deps-dev): bump puppeteer from 24.40.0 to 24.41.0 (#6508) chore(deps-dev): bump typedoc from 0.28.18 to 0.28.19 (#6505) chore(deps): bump ts-morph from 27.0.2 to 28.0.0 (#6506) chore(deps-dev): bump globals from 17.4.0 to 17.5.0 (#6504) ...
marikaner
left a comment
There was a problem hiding this comment.
I left a few comments, please especially take note of the ones with "[req]". But no big blockers.
| this.cache.delete(key!); | ||
| this.cache.set(key!, entry); |
There was a problem hiding this comment.
[q] is the ! needed? There is a nullish check on the top.
There was a problem hiding this comment.
It was needed before the refactoring, I was able to remove them now.
| ) { | ||
| // Evict the least recently used (LRU) entry | ||
| const lruKey = this.cache.keys().next().value; | ||
| this.cache.delete(lruKey!); // SAFETY: size > 0 |
There was a problem hiding this comment.
[q] What does the comment tell me?
There was a problem hiding this comment.
The comment explains why the ! operator is safe to apply here.
| ): T { | ||
| if (!key) { | ||
| return computeFn().entry; | ||
| } |
There was a problem hiding this comment.
[req] I wasn't sure about this, because it seems a little off: It is weird, that this just calls the compute function without caching it. But, when you have a case where the key might not be defined and you want to have a default you don't have to differentiate the cases. So I guess it is better as is.
But, I am missing signs that this is intended, though, aka. a test and docs.
There was a problem hiding this comment.
I've removed this special handling, I added in on purpose but is currently not a useful feature in practice.
* origin/main: chore: Replace yarn with pnpm (#6448) chore: Reorder step configurations (#6521) chore(deps): bump bignumber.js from 10.0.2 to 11.0.0 (#6520) chore(deps): bump fast-xml-parser from 5.6.0 to 5.7.1 (#6519) feat: Add `getIasToken()` and `getIasDestination()` convenience functions (#6431) chore(deps-dev): bump memfs from 4.57.1 to 4.57.2 (#6516) chore: Correct merge-and-write-changelogs action path in package.json (#6479) chore(deps-dev): bump turbo from 2.8.10 to 2.9.6 (#6499)
Closes https://github.com/SAP/cloud-sdk-backlog/issues/1298
keepAlive === true)getOrInsertComputed()toCache<_>(likeMap.prototype.getOrInsertComputed())