Skip to content

🧱 refactor(cache): derive usage_samples insert/normalize SQL from one bucket descriptor table + schema parity test #427

Description

@martinciu

🔍 Problem

Adding one Anthropic usage bucket to usage_samples touches 4+ positionally-coupled sites with no parity check:

  • 🪦 A hand-written (pct, resets_at) column pair in pkg/cache/schema.sql:40-79
  • 🪦 A hand-written UPDATE line in normalizeResetsAtSQL (pkg/cache/cache.go:84-95)
  • 🪦 A positional bucketArgs(u.X) append in RecordUsageSample (cache.go:253-297) that must stay in lockstep with the hand-written column order in insertUsageSampleSQL — 19 ? placeholders counted by eye
  • 🪦 Optionally an entry in the utilizationColumns allowlist (cache.go:422-425)

The bucket list is demonstrably still growing (tangelo, iguana_necktie, omelette_promotional are recent additions), and the args↔columns positional coupling is exactly the silent-transposition bug class that derivation eliminates. Nothing at compile time or test time checks that ordering matches.

🛠️ Suggested shape

Declare one ordered descriptor table:

var usageBucketCols = []struct {
    name string
    get  func(anthro.Usage) *anthro.Bucket
}{ ... }

and derive insertUsageSampleSQL, normalizeResetsAtSQL, and the args slice from it at init. schema.sql stays hand-written, but add a parity test asserting the column set matches the descriptor table — that's what keeps the risk down. No schema bump required.

⚠️ Notes

  • SQL generated at init needs the parity test against schema.sql to be trustworthy; without it this refactor trades one hazard for another.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgoPull requests that update go codeimportance: lowPolish, refactor, or nice-to-havesize: mMedium — 1 to 3 hours

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions