mirror of
https://github.com/coder/coder.git
synced 2026-11-01 21:06:07 +08:00
Follow-up to the review discussion on the price book refresh automation: https://github.com/coder/coder/pull/28146#discussion_r3806439966 ## Problem The price seed row struct was duplicated three times, so a JSON tag change had to be repeated in each copy: - `scripts/aibridgepricesgen.priceRow` - `scripts/aibridgepricesdiff.priceRow` - `coderd/aibridge/prices.seedRow` The `(provider, model)` key and its parsing were duplicated too. ## Change Add `coderd/aibridge/prices/pricebook` holding the shared contract: `Row`, `Key`, `Row.Key()`, and `Parse`. The package depends only on the standard library, so the scripts can import it without pulling in the database layer that `coderd/aibridge/prices` brings. Consumer-specific behaviour stays where it is: upstream conversion and validation in the generator, comparison and Markdown rendering in the diff tool, DB seeding and runtime lookup in the seeder. The batch SQL upsert still extracts JSON fields by name, so it remains a separate contract boundary. The note about keeping it in sync now lives on the shared `Row`. No generated artifacts change; the serialized schema is identical. --- <sub>Opened by Coder Agents on behalf of @evgeniy-scherbina.</sub>
42 lines
1.3 KiB
Go
42 lines
1.3 KiB
Go
// Package prices seeds the ai_model_prices table from an embedded JSON
|
|
// price book at server startup.
|
|
package prices
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/coder/coder/v2/coderd/aibridge/prices/pricebook"
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
)
|
|
|
|
//go:embed data/prices.json
|
|
var seedJSON []byte
|
|
|
|
// Seed applies the embedded price seed to ai_model_prices table, replacing the
|
|
// price columns of any existing (provider, model) row and inserting new ones.
|
|
// Rows already in the table that no longer appear in the seed are left
|
|
// untouched, so historical entries persist across upstream model deprecations.
|
|
func Seed(ctx context.Context, db database.Store) error {
|
|
return SeedFromBytes(ctx, db, seedJSON)
|
|
}
|
|
|
|
// SeedFromBytes applies an arbitrary JSON seed. Most callers should use Seed,
|
|
// which applies the seed embedded in this binary; SeedFromBytes is exposed
|
|
// for tests that need to inject a deterministic seed.
|
|
func SeedFromBytes(ctx context.Context, db database.Store, data []byte) error {
|
|
rows, err := pricebook.Parse(data)
|
|
if err != nil {
|
|
return xerrors.Errorf("parse price seed: %w", err)
|
|
}
|
|
if len(rows) == 0 {
|
|
return xerrors.New("price seed is empty")
|
|
}
|
|
return db.UpsertAIModelPrices(ctx, database.UpsertAIModelPricesParams{
|
|
Seed: data,
|
|
Source: database.AIModelPriceSourceDefault,
|
|
})
|
|
}
|