Skip to content

feat(azure compute): populate vCPU + MemoryGB via cached SKU catalogue (closes #148)#229

Merged
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/issue-148-azure-compute-vcpu-memory
May 3, 2026
Merged

feat(azure compute): populate vCPU + MemoryGB via cached SKU catalogue (closes #148)#229
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/issue-148-azure-compute-vcpu-memory

Conversation

@cristim
Copy link
Copy Markdown
Member

@cristim cristim commented May 3, 2026

Summary

Wires Azure compute to the lazy SKU-catalogue lookup pattern from PR #81, so convertAzureVMRecommendation now populates common.ComputeDetails.VCPU and common.ComputeDetails.MemoryGB from armcompute.ResourceSKUsClient.NewListPager capabilities. Both prerequisites are now in place: PR #97 added the destination fields (with omitempty JSON tags), and PR #81 landed the cache pattern for the other three Azure services.

Closes #148.

Why

common.ComputeDetails.GetDetailDescription() already reads VCPU and MemoryGB and appends " (<vcpu> vCPU / <memory> GB)" when both are >0. Pre-PR, Azure VM recommendations always had both at 0, so the size string was suppressed and the UI rendered SKU names alone (e.g. Standard_D2s_v3). Post-PR they render as Standard_D2s_v3 (2 vCPU / 8 GB).

What changed

  • providers/azure/services/compute/client.go:

    • New unexported vmSKUEntry{vCPUs, memoryGB}.
    • New skuCacheOnce sync.Once + skuCacheMap map[string]vmSKUEntry on ComputeClient.
    • cachedSKULookup(ctx, skuName) — lazy single-fetch, O(1) lookup thereafter.
    • fetchSKUCatalogue(ctx) — reuses the existing createResourceSKUsPager and isAvailableInRegion helpers (already used by GetValidResourceTypes); returns nil on error.
    • populateVMSKUMapFromPage extracted out of fetchSKUCatalogue to stay under the project's gocyclo=10 threshold (matches the cache/database extraction pattern from PR perf(azure): batched SKU catalogue lookup eliminates N+1 in recommendation converters #81).
    • extractVMSKUCapabilities parses vCPUs (Atoi) and MemoryGB (ParseFloat) from the SKU's name/value capability list.
    • convertAzureVMRecommendation takes ctx (was _) and populates Details.VCPU/MemoryGB from the cache when both >0. Single caller GetRecommendations already passes ctx.
  • providers/azure/services/compute/client_test.go: 4 new tests

    • _PopulatesVCPUAndMemoryFromSKUCache — catalogue hit → fields enriched.
    • _PagerErrorFallsBack — fetch error → fields stay 0; conversion succeeds.
    • _NoMatchLeavesFieldsZero — catalogue miss → fields stay 0.
    • _CachedSKULookup_FetchedOnce — 10 lookups → 1 NextPage call (pins the N+1 invariant).

The shared mocks.MockResourceSKUsPager doesn't expose its page counter and can't simulate a NextPage error, so the tests use a small file-scoped vmSKUCatalogueMockPager (matches the cosmosdb/cache test convention where each service defines its own catalogue mock). No change to the shared mocks surface.

Graceful-degradation contract

A transient ResourceSKUsClient failure no longer breaks Azure VM recommendation conversion: VCPU/MemoryGB stay at 0 (the omitempty JSON tags hide them from API payloads), the rest of Details is populated from the recommendation payload as before, and a WARN is logged once per client lifetime. Matches the contract from cache/cosmosdb/database in PR #81.

Out of scope

  • AWS / GCP compute converter wiring (separate follow-ups, per the issue body).
  • Platform / Tenancy / Scope enrichment — those need additional Azure data sources beyond armcompute.ResourceSKU.Capabilities.
  • No schema change to common.ComputeDetails (fields already added in PR perf(common): extend ComputeDetails with VCPU + MemoryGB #97).

Test plan

  • go build ./...
  • go test github.com/LeanerCloud/CUDly/providers/azure/services/compute — 42 passed (4 new + all existing)
  • go test github.com/LeanerCloud/CUDly/providers/azure/... — 309 passed across 10 packages (the pre-existing providers/azure/services/search build failure is unrelated — go.sum drift)
  • go test ./... from pkg/ — 319 passed
  • go vet ./... — clean
  • gofmt -l . — empty
  • gocyclo -over 10 on the modified file — no offenders

Summary by CodeRabbit

  • Enhancements
    • Azure VM recommendations now include detailed vCPU and memory capacity information.
    • Improved performance through intelligent caching of Azure VM specification data.
    • Enhanced reliability with graceful fallback handling when specification data is unavailable.

closes #148)

PR #97 added VCPU + MemoryGB fields to common.ComputeDetails (with
omitempty JSON tags). PR #81 introduced the lazy SKU-catalogue pattern
for cache/cosmosdb/database but explicitly scoped back compute because
the destination fields didn't exist. Both prerequisites are now in
place; this wires Azure compute to the same pattern.

Implementation mirrors cache/database verbatim for consistency:

- New unexported vmSKUEntry{vCPUs, memoryGB}.
- New skuCacheOnce sync.Once + skuCacheMap field on ComputeClient.
- cachedSKULookup(ctx, skuName) lazily triggers the catalogue fetch on
  first call; subsequent calls are O(1) map lookups. ok=false on miss
  or fetch error.
- fetchSKUCatalogue reuses the existing createResourceSKUsPager and
  isAvailableInRegion helpers (already used by GetValidResourceTypes),
  walks every page, and reduces virtualMachines SKUs into the map.
  Returns nil on error so the sync.Once-gated cache stays nil and
  converters fall back to the empty-fields path with a one-time WARN.
- extractVMSKUCapabilities pulls vCPUs (Atoi) and MemoryGB
  (ParseFloat) from the SKU's Capabilities name/value list. Unparseable
  or missing capabilities → 0, treated as "unknown".
- populateVMSKUMapFromPage was extracted out of fetchSKUCatalogue to
  stay under the project's gocyclo=10 threshold (matches the
  cache/database extraction pattern from PR #81).
- convertAzureVMRecommendation now takes ctx (was _) and populates
  Details.VCPU/MemoryGB from the cache when both >0. The single caller
  GetRecommendations already passes ctx; no public API change.

Behaviour preserved on failure: a transient ResourceSKUsClient error
no longer breaks the conversion — VCPU/MemoryGB stay at 0 (omitempty
hides them from API payloads), the rest of Details is populated from
the recommendation payload as before, and a WARN is logged once per
client lifetime.

UX improvement: common.ComputeDetails.GetDetailDescription appends
" (<vcpu> vCPU / <memory> GB)" when both fields are >0, so Azure VM
recommendation summaries now include the size string instead of the
SKU name alone.

Tests added in providers/azure/services/compute/client_test.go
(file-scoped vmSKUCatalogueMockPager keeps the shared
mocks.MockResourceSKUsPager surface untouched, mirroring the
cosmosdb / cache test convention):

- TestComputeClient_ConvertAzureVMRecommendation_PopulatesVCPUAndMemoryFromSKUCache:
  catalogue hit populates VCPU=2, MemoryGB=8 for Standard_D2s_v3.
- TestComputeClient_ConvertAzureVMRecommendation_PagerErrorFallsBack:
  fetch error leaves both fields at 0; conversion succeeds.
- TestComputeClient_ConvertAzureVMRecommendation_NoMatchLeavesFieldsZero:
  catalogue miss leaves both fields at 0; conversion succeeds.
- TestComputeClient_CachedSKULookup_FetchedOnce: 10 lookups trigger
  exactly 1 NextPage call (pins the N+1 invariant per PR #81).

Out of scope (separate follow-ups, per the issue body):

- AWS / GCP compute converter wiring.
- Platform / Tenancy / Scope enrichment (require non-ResourceSKUs
  Azure data sources).

Verification: gofmt clean; go vet ./... clean; gocyclo -over 10 finds
no offenders in the modified file; go test
github.com/LeanerCloud/CUDly/providers/azure/services/compute → 42
passing (4 new + all existing). The pre-existing
providers/azure/services/search build failure (missing go.sum entry)
is unrelated to this change.

Closes #148
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc167cdd-870f-4e0e-a5d3-34ef9e8696b4

📥 Commits

Reviewing files that changed from the base of the PR and between c84fd02 and aca5938.

📒 Files selected for processing (2)
  • providers/azure/services/compute/client.go
  • providers/azure/services/compute/client_test.go

📝 Walkthrough

Walkthrough

Azure Compute recommendations are enriched with vCPU and MemoryGB data via a lazily-cached SKU catalogue. The ComputeClient fetches ARM Resource SKUs once per lifetime, parses capabilities, and the recommendation converter populates ComputeDetails from the cache with graceful fallback to zero on failures.

Changes

Azure SKU-Based Compute Enrichment

Layer / File(s) Summary
Data Model
providers/azure/services/compute/client.go
vmSKUEntry struct holds parsed vCPUs and memoryGB; ComputeClient gains skuCacheOnce and skuCacheMap fields for per-client-lifetime cache.
Cache Initialization & Lookup
providers/azure/services/compute/client.go
fetchSKUCatalogue fetches the ARM SKU catalogue once via pager, populateVMSKUMapFromPage extracts region-specific VM SKUs, and extractVMSKUCapabilities parses vCPU/MemoryGB from capability pairs; cachedSKULookup wraps with sync.Once and returns (entry, hit) or (empty, false).
Recommendation Conversion
providers/azure/services/compute/client.go
convertAzureVMRecommendation enriches ComputeDetails with InstanceType, VCPU, and MemoryGB from the SKU cache; logs warnings and degrades to zero on cache miss or fetch error.
Tests & Helpers
providers/azure/services/compute/client_test.go
Mock pager vmSKUCatalogueMockPager and buildVMSKU helper support four tests: SKU cache population, pager error fallback, missing SKU fallback, and single-fetch-per-lifetime invariant.

Sequence Diagram

sequenceDiagram
    participant Converter as convertAzureVMRecommendation
    participant Client as ComputeClient
    participant Cache as SKU Cache<br/>(sync.Once)
    participant Pager as ResourceSKUsClient<br/>Pager
    participant ARM as Azure SKUs<br/>API

    Note over Converter,ARM: First recommendation conversion
    Converter->>Client: cachedSKULookup(vmName)
    Client->>Cache: Check cache (sync.Once gate)
    alt Cache not yet initialized
        Cache->>Pager: fetchSKUCatalogue()
        Pager->>ARM: ListByLocation(region) paginated
        ARM-->>Pager: SKU pages
        Pager->>Cache: Build name→{vCPU, MemoryGB} map
        Cache-->>Client: Return (entry, hit)
    else Cache already initialized
        Cache-->>Client: Return (entry, hit)
    end
    Client-->>Converter: {vCPUs, MemoryGB}
    Converter->>Converter: Populate ComputeDetails

    Note over Converter,ARM: Second recommendation (same client)
    Converter->>Client: cachedSKULookup(otherVmName)
    Client->>Cache: Check cache (sync.Once skipped)
    Cache-->>Client: Return from map (no API call)
    Client-->>Converter: {vCPUs, MemoryGB}
    Converter->>Converter: Populate ComputeDetails
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

triaged, priority/p3, severity/low, impact/few, type/feat

Poem

🐰 A rabbit caches Azure SKUs,
One fetch per lifetime—no N+1 blues!
vCPUs and memory now brightly glow,
Recommendations enriched, fast and low.
Hops through the pager, once and for all! 💾

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly describes the primary change: populating vCPU and MemoryGB fields in Azure compute recommendations using a cached SKU catalogue, and correctly references the closing issue #148.
Linked Issues check ✅ Passed The PR successfully implements the Step 3 (Wire Azure) portion of issue #148: it adds cachedSKULookup pattern, wires convertAzureVMRecommendation to populate VCPU/MemoryGB from the SKU catalogue with graceful degradation, and includes comprehensive tests for SKU cache hits, errors, misses, and fetch-once invariant.
Out of Scope Changes check ✅ Passed All changes align with the Azure wiring scope of issue #148; the PR explicitly defers AWS/GCP converter updates and other cross-cutting work to follow-ups, maintaining focused scope.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-148-azure-compute-vcpu-memory

Review rate limit: 2/5 reviews remaining, refill in 29 minutes and 19 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 3, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim cristim added priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-quarter Within the quarter impact/many Affects most users effort/m Days type/feat New capability triaged Item has been triaged labels May 3, 2026
cristim added a commit that referenced this pull request May 3, 2026
)

A fork that pushes a PR, pings CodeRabbit, then exits leaves CR threads
unresolved — exactly what happened to PRs #228, #229, #230, etc., where
CR posted Actionable findings + Nitpicks that were never triaged.

This adds a paragraph to the CR-loop section explicitly addressing the
delegation case: subagent prompts MUST include the full loop with the
exit criteria spelled out. Stops the failure mode where the rule is
correctly stated for humans but doesn't get mirrored into fork prompts.
@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 3, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
Copy link
Copy Markdown
Member Author

cristim commented May 3, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim cristim merged commit c05c0d1 into feat/multicloud-web-frontend May 3, 2026
5 checks passed
@cristim cristim deleted the feat/issue-148-azure-compute-vcpu-memory branch May 3, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/many Affects most users priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/feat New capability urgency/this-quarter Within the quarter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant