Repository navigation
refactor(gcp): share the savings and tier-matching helpers - #634
Conversation
Move the savings-percentage formula and the SKU tier matcher, copied verbatim in cloudsql, cloudstorage and memorystore, into internal/skumatch as SavingsPercent and MatchesTier. Callers switched, copies deleted; behavior is unchanged. Closes #95 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Shared billing resolution providers/gcp/internal/skulist/* |
Adds a shared billing-service interface and resolver. The real service lists SKU pages and wraps client-creation and listing errors. |
Shared SKU matching and pricing helpers providers/gcp/internal/skumatch/* |
Adds shared tier-and-region matching, unit-price extraction, and savings calculation, with tests for their behavior. |
Cloud SQL pricing integration providers/gcp/services/cloudsql/* |
Uses shared billing and SKU helpers, rejects non-positive prices, and adds negative-price tests. |
Cloud Storage pricing integration providers/gcp/services/cloudstorage/* |
Uses shared billing resolution and savings calculation, rejects non-positive prices, and adds negative-price tests. |
Memorystore pricing integration providers/gcp/services/memorystore/* |
Uses shared billing and SKU helpers, rejects non-positive prices, and updates related pricing tests. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Refactor
Possibly related PRs
- LeanerCloud/cloud-commitments-go#632: Names billing service IDs used by Cloud SQL and Cloud Storage SKU listing.
- LeanerCloud/cloud-commitments-go#471: Adds shared SKU matching and price aggregation code used by this change.
- LeanerCloud/cloud-commitments-go#628: Adds a commitment-price API used by the pricing extractors.
Suggested reviewers: iamjsd
Merge Risk: 
Minimal · up to b8001
-
No actionable pricing regression is identified; the change appears mergeable after normal checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed -
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
…ients Move the BillingService interface, the real Cloud Billing wrapper and the get-or-create logic, identical in cloudsql, cloudstorage and memorystore except for the service name, into internal/skulist. Each client keeps BillingService as an alias so its mocks are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
extractSQLPriceFromSKU (cloudsql) and extractPriceFromSKU (memorystore) were identical. Replace both with skumatch.UnitPrice. cloudstorage keeps its own extractor because it also converts usage units. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pricing guards in cloudsql, memorystore and cloudstorage rejected only zero. A negative catalog price passed them and flipped the sign of the savings percentage. Reject <= 0 and fail closed; one test per service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review verdicts at 9575b16: two independent cold reviews (non-author), both APPROVE, after one fix round.
Refs #95: the issue stays open for the remaining duplication listed in the PR body. [claude-cc-libs] |
Refs #95
Moves the duplicated GCP helpers into shared internal packages, parameterising only the service name where needed.
Lifted:
skumatch.SavingsPercent(wascalculateSQLSavingsPercentage,calculateStorageSavingsPercentage,calculateSavingsPercentage) andskumatch.MatchesTier(wasskuMatchesTierin cloudsql and memorystore).skulist.BillingService, the real Cloud Billing wrapper andskulist.Resolve(ctx, existing, name, opts...)(wasBillingService,realBillingServiceandgetOrCreateBillingServicex3). Each client keepstype BillingService = skulist.BillingService, so its mocks are unchanged.skumatch.UnitPrice(wasextractSQLPriceFromSKUin cloudsql andextractPriceFromSKUin memorystore).All copies were identical, so there are no edge-case differences. A zero on-demand total still yields NaN/Inf in
SavingsPercent; callers reject non-positive prices first.Hardening (separate commit): the on-demand and commitment guards in all three clients rejected only
== 0; they now reject<= 0, because a negative catalog price flips the savings sign. One test per service.Still duplicated, so this does not close the issue:
listSKUscatalog cache (cloudsql, memorystore, cloudstorage)extract*PricingFromSKUsslot loops (cloudsql and memorystore nearly identical; cloudstorage differs)extractStoragePriceFromSKU, which also converts usage units, so it is not a copy ofUnitPriceTests: new table tests for
SavingsPercent,MatchesTier,UnitPrice,Resolve, and the negative-price guards. Existing tests changed only to call the moved helpers (skumatch.MatchesTier,skumatch.UnitPrice); assertions are unchanged.go test -race -count=1 ./...passes in providers/gcp with GOWORK=off and in the workspace; golangci-lint v2.10.1: 0 issues.Mutation probes, each reverted: flipping the
SavingsPercentsubtraction,&&to||inMatchesTier, sign and no-pricing branch inUnitPrice, theexistingcheck and the error label inResolve, and each of the six<= 0guards all fail tests.Note: the first commit message contains
Closes #95; if this is merged without squashing, that would close the issue.🤖 Generated with Claude Code
Summary by CodeRabbit