Skip to content

perf(azure): batched SKU catalogue lookup to populate deferred Details fields without N+1 API calls #49

@cristim

Description

@cristim

Summary

The four Azure recommendation converters (compute, database, cache, cosmosdb) populate the subset of Details derivable from the reservation recommendation payload only. SDK-catalogue-derived fields — compute Platform/Tenancy/Scope + memory/vCPU, database EngineVersion/AZConfig, cache Shards, cosmos APIType — are deliberately left empty because populating them inline would produce an N+1 API call per recommendation.

Captured in: known_issues/10_azure_provider.md ("New follow-ups surfaced during this resolution" → MEDIUM: Azure converters leave SKU-lookup Details fields empty (deferred N+1 avoidance)).

Current behaviour

Each convertAzure*Recommendation builds a partial Details:

  • providers/azure/services/compute/client.go:703common.ComputeDetails{InstanceType: f.ResourceType} only.
  • providers/azure/services/database/client.go:608common.DatabaseDetails{Engine: "sqlserver", InstanceClass: f.ResourceType} only.
  • providers/azure/services/cache/client.go:582common.CacheDetails{...} partial.
  • providers/azure/services/cosmosdb/client.go:617common.NoSQLDetails{Engine: "cosmos", ThroughputUnits: parsed} only; APIType missing.

Fields requiring SDK calls are deferred:

  • Compute: armcompute.ResourceSKUsClient.ListByLocation for vCPU/MemoryGB/Tenancy/Scope.
  • Database: armsql SKU catalogue for EngineVersion/AZConfig/Deployment.
  • Cache: armredis for Shards/Tier.
  • Cosmos: armcosmos.DatabaseAccountsClient for APIType (sql/mongodb/cassandra/gremlin/table).

Steps to reproduce

  1. Run GetRecommendations against an Azure subscription.
  2. Inspect any returned Recommendation.Details — compute MemoryGB == 0, database EngineVersion == "", cache Shards == 0, cosmos APIType == "".
  3. UI rendering treats these as "unknown" and hides the corresponding columns.

Expected behaviour

Full Details population so the UI can render vCPU, memory, engine version, and Cosmos API type without hitting "unknown".

Proposed fix

Single-shot batched SKU lookup per region per service, called ONCE at the start of GetRecommendations for each region appearing in the response, cached in a map[skuName]SKUCatalogueEntry, then consulted as the converter builds each rec's Details. No N+1 storm, full Details population.

Per-service batch endpoints:

  • armcompute.ResourceSKUsClient.ListByLocation(region)
  • armsql.SKUsClient.ListByServer(...)
  • armredis.SKUsClient.ListByLocation(region)
  • armcosmos.DatabaseAccountsClient.ListByResourceGroup(rg)

Test plan

Per service: a fixture with SKU-specific properties + an assertion that the resulting Details is non-nil and has the expected concrete type + fields. Mock the catalogue lookup to return a known SKU entry; assert the converter consumed it correctly.

References

  • Files: providers/azure/services/{compute,database,cache,cosmosdb}/client.go::convertAzure*Recommendation.
  • Known-issue doc: known_issues/10_azure_provider.md → "New follow-ups surfaced during this resolution".

Severity

Medium — UI degrades to "unknown" for fields that exist in the SDK catalogue. Functional but loses the resolution the catalogue would provide.

Effort

Medium — each service is ~30 LOC for the batched lookup + cache + ~30 LOC for converter wiring + a fixture test.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions