Skip to content

azure: Add in-memory cache for Azure location/provider API calls#2239

Merged
alexweininger merged 7 commits intomainfrom
alex/location-cache
Mar 25, 2026
Merged

azure: Add in-memory cache for Azure location/provider API calls#2239
alexweininger merged 7 commits intomainfrom
alex/location-cache

Conversation

@alexweininger
Copy link
Copy Markdown
Member

LocationCache deduplicates concurrent requests and caches results across wizard instances within a single extension activation. Wired into getAllLocations and getProviderLocations in LocationListStep.

LocationCache deduplicates concurrent requests and caches results across wizard instances within a single extension activation. Wired into getAllLocations and getProviderLocations in LocationListStep.
@alexweininger alexweininger requested a review from a team as a code owner March 25, 2026 17:12
Copilot AI review requested due to automatic review settings March 25, 2026 17:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an in-memory cache to deduplicate and reuse Azure location/provider API calls across wizard instances within a single extension activation.

Changes:

  • Introduces LocationCache with in-flight request deduplication and optional TTL.
  • Wires caching into getAllLocations and getProviderLocations.
  • Adds unit tests covering cache hits, concurrency dedupe, TTL expiry, and error behavior.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
azure/src/wizard/LocationCache.ts Implements the shared in-memory cache + singleton caches.
azure/src/wizard/LocationListStep.ts Routes subscription/provider location lookups through the cache.
azure/test/LocationCache.test.ts Adds unit tests for caching, concurrency, TTL, and error handling.
azure/src/index.ts Exports LocationCache and the singleton caches from the package entrypoint.
azure/index.d.ts Publishes type declarations for the new cache API/exports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread azure/src/wizard/LocationCache.ts Outdated
Comment on lines +52 to +59
const promise = loader().then(data => {
this.cache.set(key, { data, storedAt: Date.now() });
this.inflight.delete(key);
return data;
}).catch(err => {
this.inflight.delete(key);
throw err;
});
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling clear() can be undone by currently in-flight requests: once they resolve, they will repopulate this.cache via this.cache.set(...), potentially reintroducing stale entries right after a sign-out/subscription change. Consider clearing inflight as well, or introduce a cache 'generation' token checked before writing results (ignore writes from older generations).

Copilot uses AI. Check for mistakes.
Comment thread azure/src/wizard/LocationCache.ts Outdated
Comment on lines +65 to +69
/** Remove all entries (e.g. on sign-out or subscription change) */
clear(): void {
this.cache.clear();
// Don't clear inflight — let pending requests finish naturally
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling clear() can be undone by currently in-flight requests: once they resolve, they will repopulate this.cache via this.cache.set(...), potentially reintroducing stale entries right after a sign-out/subscription change. Consider clearing inflight as well, or introduce a cache 'generation' token checked before writing results (ignore writes from older generations).

Copilot uses AI. Check for mistakes.
Comment thread azure/src/wizard/LocationCache.ts Outdated
return existing;
}

const promise = loader().then(data => {
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loader() can throw synchronously before returning a Promise. In that case, inflight is never set, and callers won't get consistent dedup/error behavior. Wrap the call so sync throws become a rejected Promise (e.g., start from Promise.resolve().then(loader)), and ensure inflight bookkeeping is consistent.

Suggested change
const promise = loader().then(data => {
const promise = Promise.resolve().then(loader).then(data => {

Copilot uses AI. Check for mistakes.
Comment thread azure/test/LocationCache.test.ts Outdated
Comment on lines +96 to +97
// Wait for expiry
await new Promise(r => setTimeout(r, 10));
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This time-based test can be flaky under slow/loaded CI agents. Prefer fake timers (if the repo test stack supports them) or otherwise make the timing deterministic (e.g., inject a clock into LocationCache for tests) to avoid intermittent failures.

Copilot uses AI. Check for mistakes.
Comment thread azure/src/index.ts Outdated
export * from './utils/setupAzureLogger';
export * from './utils/uiUtils';
export * from './wizard/LocationListStep';
export { LocationCache, subscriptionLocationsCache, providerLocationsCache } from './wizard/LocationCache';
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exporting the singleton caches (subscriptionLocationsCache, providerLocationsCache) makes them part of the package’s public API (also reflected in index.d.ts). If these are intended to be internal implementation details, consider not exporting them (or marking as internal/unstable) to avoid external consumers depending on shared global state that may need to change later.

Suggested change
export { LocationCache, subscriptionLocationsCache, providerLocationsCache } from './wizard/LocationCache';
export { LocationCache } from './wizard/LocationCache';

Copilot uses AI. Check for mistakes.
Comment thread azure/src/wizard/LocationCache.ts Outdated
alexweininger and others added 3 commits March 25, 2026 14:49
Promise.resolve().then(loader) deferred loader execution to a microtask,
which meant concurrent getOrLoad calls couldn't detect the in-flight
request because the loader hadn't run yet. Call loader() directly with
a try-catch for sync throws instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Log cache misses and successful fetches in getAllLocations and
getProviderLocations using ext.outputChannel.appendLog.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants