db

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 9, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package db persists parsed budgetclaw events and their per-day rollups in a local SQLite database.

Two tables:

events   one row per (uuid) billable assistant message.
         UUID is the primary key and dedupe guarantee: re-inserting
         the same event is a no-op. Frozen historical fact.
rollups  one row per (project, git_branch, day) aggregate.
         Updated atomically with the event insert so the budget
         evaluator can do O(1) reads for cap checks.

SQLite is opened with WAL journal mode on file-backed databases, enabling the CLI to read while the watcher writes from a separate process. The driver is modernc.org/sqlite (pure Go, no cgo) so the static-binary pledge holds.

Costs are passed in from the caller at insert time and stored as historical fact. The db package has no dependency on the pricing table. A future Anthropic rate change will not retroactively re-price old events.

Day boundaries in rollups are UTC. Budget evaluators that need local-timezone semantics should use RollupSum over a UTC time range computed from the user's tz, not the day string directly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB wraps a *sql.DB with budgetclaw-specific methods.

func Open

func Open(path string) (*DB, error)

Open opens or creates the state database.

If path is empty, Open resolves the default location via paths.StateDir() (honoring XDG_STATE_HOME) and creates any missing parent directories. If path is the literal string ":memory:", Open returns an in-memory database suitable for tests.

The schema is applied on every call. Existing tables are not recreated thanks to IF NOT EXISTS.

func OpenMemory

func OpenMemory() (*DB, error)

OpenMemory returns an in-memory database for tests. Equivalent to Open(":memory:") but avoids forcing test code to know the magic string.

func (*DB) Close

func (d *DB) Close() error

Close closes the underlying connection.

func (*DB) Insert

func (d *DB) Insert(ctx context.Context, e *parser.Event, costUSD float64) error

Insert stores a billable event and updates its rollup row inside a single transaction. Idempotent on e.UUID: re-inserting the same event is a no-op (the rollup is not double-counted).

costUSD is passed in so the db package stays independent of the pricing table. Callers should compute it via pricing.CostForModel before calling Insert.

func (*DB) RollupForDay

func (d *DB) RollupForDay(ctx context.Context, project, branch string, day time.Time) (*Rollup, error)

RollupForDay returns the rollup row for a specific (project, branch, day). Returns (nil, nil) if the row does not exist — "nothing spent today" is a valid state, not an error.

func (*DB) RollupSum

func (d *DB) RollupSum(ctx context.Context, project, branch string, start, end time.Time) (*Rollup, error)

RollupSum returns the sum across a date range for a single (project, branch). Range is inclusive on both ends. Returned Rollup has empty Day and (Project, GitBranch) copied from args so callers don't need to re-thread them.

Used by the budget evaluator for weekly/monthly caps, and by the CLI for "status --period=week" output.

func (*DB) StatusByProject

func (d *DB) StatusByProject(ctx context.Context, start, end time.Time) ([]Rollup, error)

StatusByProject returns rollup totals grouped by (project, branch) across a date range. Ordered by project then branch for deterministic CLI output.

Empty result is not an error — a user with nothing tracked yet gets a nil slice and no rows.

type Rollup

type Rollup struct {
	Project            string
	GitBranch          string
	Day                string
	EventCount         int
	InputTokens        int
	OutputTokens       int
	CacheReadTokens    int
	CacheWrite5mTokens int
	CacheWrite1hTokens int
	CostUSD            float64
}

Rollup is one (project, branch, day) aggregate. For range-sum queries, Day is empty because the result spans multiple days.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL