Repository navigation
fix(azure): dedupe Redis recommendations against held reservations - #706
Conversation
managedredis read the Consumption reservation-details feed, which has no purchase date, quantity or location, so every held Redis reservation was invisible to the duplicate guard. It now lists reservations through the shared Reservations API path, as compute does, and fails closed on incomplete live rows. The old seam's tests move to the new one. Fixes #699 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round-trips a raw Consumption recommendation through a captured purchase body into the held reservation, then checks the reduction, the state/scope/date/region/SKU table, fail-closed rows, the variant shared-budget behavior (go#703) and the default inventory wiring. Refs #699 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The missing-quantity and expiry-today rows now assert their error text, and the CHANGELOG lists the removed ReservationsDetailsPager seam as a source break. Refs #699 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 53 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Action not completed
|
|
APPROVED b95124e by claude-qa-ui-4
PurchaseDate is date-only, so StartDateIsDay keeps the reservation counted until 24h after the purchase day (pkg/recfilter/dedupe.go:134-136), which errs toward suppression.
Runs (GOWORK=off, GOMAXPROCS=4, -p 2): build and vet pass; go test passes for managedredis, internal/reservations, compute and cache; golangci-lint reports 0 issues. 16 probes, all killed by managedredis tests:
Non-blocking:
|
|
APPROVED b95124e by claude-cc-libs Cold, non-author review of the change against main (c83aef8), including tests and mutation probes. The PR moves managedredis inventory to the Reservations API path compute uses, which is the source #699 recommended. It does not patch the ReservationDetail usage row. Blocking: none. Non-blocking
Checked
Mutation probes: 9 of 9 killed. They covered dropping StartDate, dropping Commands
|
|
Merge gate at b95124e:
|
Drop the stale held-reservation caveat (fixed by #706) and note that Shards is no longer reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ducer (#702) * feat(azure/managedredis): export ReservationUnitPrice Advisor pricing looks up a reservationUnitPricer per service. managedredis only had the private getRedisPricing, so routing Redis rows through it would skip every row. Export the same wrapper the cache client has. Unknown prices and unsupported SKU identities return an error, never 0. Refs #692 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(azure): collect and price Redis through managedredis (ServiceMemoryDB) Azure Redis recommendations were labeled ServiceCache, a service whose client is about to stop buying Redis. Swap the single Redis producer in the aggregate and Advisor paths from the cache client to managedredis, so every Redis recommendation carries ServiceMemoryDB: - the seam newCacheClientFn becomes newManagedRedisClientFn - the Redis service filter follows ServiceMemoryDB - the Advisor rediscache mapping resolves to memorydb, so coverage by Consumption rows keeps matching on the same service label - Advisor rows are priced through managedredis.ReservationUnitPrice A guard test asserts no returned recommendation has Service ServiceCache. Refs #692 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(azure/cache): stop emitting Redis recommendations (#692) managedredis is now the only producer of Azure Redis recommendations, so cache GetRecommendations becomes a documented no-op. The Consumption pager, converter, appendPage and their tests go with it. The catalogue and ReservationUnitPrice removal follows in the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(azure/cache): drop the Redis SKU catalogue and unit pricer (#692) After the recommendations no-op, nothing reads the shard-count catalogue, ReservationUnitPrice (managedredis prices Advisor rows now) or the recommendations pager. Remove them with the tests that only exercised them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changelog): note Azure Redis recommendations moved to managedredis (#692) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changelog): mark the Azure Redis moves as breaking (#692) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(azure/managedredis): price Consumption recs through ReservationUnitPrice (#692) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(azure): drop a stray empty file added by mistake (#692) providers/azure/nice was created by a mis-parsed shell command in 913cb69 and is not part of the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(azure): set CacheDetails on managedredis recommendations (#692) Engine filters and the CSV Engine column read CacheDetails, which the removed cache converter set. Restore Engine=redis and NodeType; Shards stays 0 (unknown). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changelog): correct the Azure Redis routing entry (#692) Drop the stale held-reservation caveat (fixed by #706) and note that Shards is no longer reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(azure): tag held Redis reservations with the redis engine (#692) The dedupe key includes the engine. Recommendations now carry CacheDetails.Engine "redis", so held reservations without an engine no longer reduced them (TestHeldReservation_RoundTripReducesRecommendation). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(azure): give Advisor Redis recommendations the redis engine (#692) Held Redis reservations are keyed with engine "redis", so an Advisor-only Redis row with no Details stopped being reduced by the duplicate checker. Share one managedredis.Details helper between the Consumption and Advisor paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #702 (managedredis is the only Azure Redis recommendation producer) and #706 (Redis dedupe against held reservations). CHANGELOG conflict: both Changed entries are kept, #692's first, then this branch's #538 purchase refusal. cache/client.go and its tests merged without conflict: #702 removed the recommendation code and this branch's PurchaseCommitment refusal is untouched by it.
Fixes #699.
Problem
managedredis.GetExistingCommitmentsbuilt held commitments from the ConsumptionReservationDetailusage feed. That feed has no purchase date or quantity, so every Redis commitment had a zeroStartDateand aCountof 0.recfilterdropped them as old, and even a kept one added nothing. A Redis reservation bought in the last day therefore never reduced the matching recommendation.Fix
Redis now reads held reservations from the Reservations API, through the same shared path compute uses:
internal/reservationsListAppliedReservationsandStrictCommitment, withReservedResourceTypeRedisCache.StartDatecomes from the purchase date andCountfrom the quantity. Region and SKU come from the reservation itself.The old seam (
ReservationsDetailsPagerandSetReservationsPager) is replaced bySetInventoryFactories, with a nil fallback to the default factories for both constructors. The CHANGELOG lists that as a source break; nothing outside managedredis used it.Tests
Round trip (
TestHeldReservation_RoundTripReducesRecommendation):convertRecommendation.PurchaseCommitmentfor it is captured.recfilter.NewDuplicateChecker(24).The held reservation reduces the recommendation. The test also asserts that the purchase's location equals the recommendation's region.
Table (
TestHeldReservation_Table):Variant pin: one held reservation reduces only the first term/payment variant (P1Y upfront 1, P1Y monthly 2, P3Y 2 and 2). The test pins today's behaviour and names the known over-buy, fix(recfilter): one held commitment reduces only the first term/payment variant #703.
Default inventory:
TestNewClient_DefaultInventoryFactories, for both constructors.Verification
StrictCommitmenterror ignored;GOWORK=off, build, vet andgo test ./services/...in providers/azure pass. golangci-lint at the CI version reports 0 issues, and gitleaks finds no leaks.Not verified (no live Azure account)
sku.nameandlocationin exactly the case the Consumption API uses. There is no normalisation, matching compute.Follow-ups
🤖 Generated with Claude Code