record

package
v1.2.9 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package record holds the token ledger: the index of nova-tokens' day TSVs in the fleet Redis, one hash per day: a month query reads the day hashes in one pipelined trip, so the ledger keeps one store and no second copy. The rows and the same monthly GROUP BY live here on Redis with no new dependency. The day files stay the record; the ledger is what a month query reads instead of every file.

KEY LAYOUT. tokens:ledger:<YYYY-MM-DD> is a hash. Each field is one row's key, the JSON array ["<card>","<model>","<repo>"], so (day, card, model, repo) is the primary key; each value is the JSON object {"provider","tokens","rough","sources"} whose "tokens" array carries the five types in LedgerTypes order with null for a type no source reported -- never 0, because a dash in the day file is an absence. A month is the day keys of its calendar days, read in one pipelined round trip: no SCAN, no index key to keep true.

Index

Constants

View Source
const LedgerPrefix = "tokens:ledger:"

LedgerPrefix is the owner prefix of every key this package writes.

Variables

View Source
var ErrLedgerKey = errors.New("a ledger row names day, card, model and repo")

ErrLedgerKey is a row that does not name its whole key.

View Source
var LedgerGroupings = map[string][]string{
	"model": {"model"},
	"repo":  {"repo"},
	"day":   {"day"},
	"tuple": {"day", "model", "repo"},
}

LedgerGroupings are the --by values the report takes, and the key columns each groups on.

View Source
var LedgerTypes = [5]string{"input", "output", "cache_write", "cache_read", "reasoning"}

LedgerTypes are the five token types in the order every row and report prints them.

Functions

func CheckLedgerDay

func CheckLedgerDay(day string, entries []LedgerEntry) error

CheckLedgerDay refuses a day that is not a calendar day (it names a key), and a batch that is not all of that day or repeats a key: a caller that meant two rows under one key meant their sum.

func LedgerKey

func LedgerKey(day string) string

LedgerKey is the hash that holds one day's rows.

func MonthDays

func MonthDays(month string) ([]string, error)

MonthDays are the calendar days of a YYYY-MM month.

func SortLedgerTotals

func SortLedgerTotals(t []LedgerTotal)

SortLedgerTotals is the report's order: by the key columns ascending.

Types

type LedgerDay

type LedgerDay struct {
	Day     string
	Entries []LedgerEntry
}

LedgerDay is one calendar day's batch of rows for ReplaceLedgerDays.

type LedgerEntry

type LedgerEntry struct {
	Day, Card, Model, Repo string
	Provider               string
	Tokens                 [5]int64
	Known                  [5]bool
	Rough                  int
	Sources                string
}

LedgerEntry is one ledger row. Tokens[i] counts only when Known[i].

type LedgerStore

type LedgerStore interface {
	ReplaceLedgerDay(ctx context.Context, day string, entries []LedgerEntry) error
	ReplaceLedgerDays(ctx context.Context, days []LedgerDay) error
	LedgerReport(ctx context.Context, month, by string) ([]LedgerTotal, int, int, error)
	Close() error
}

LedgerStore is the durable side of the token ledger. ReplaceLedgerDay swaps one day's rows for the given ones atomically, so indexing a day twice is the same ledger as once. ReplaceLedgerDays swaps multiple days' rows in one isolated EVAL round trip. LedgerReport is the monthly GROUP BY; indexed is how many calendar-day keys existed and missing is how many did not.

type LedgerTotal

type LedgerTotal struct {
	Day, Model, Repo string
	Rows             int
	Tokens           [5]int64
	Known            [5]bool
}

LedgerTotal is one GROUP BY group: the key columns the report grouped on (empty when not grouped on), how many ledger rows it summed, and each type's sum and whether any row reported it.

func GroupLedger

func GroupLedger(entries []LedgerEntry, by string) ([]LedgerTotal, error)

GroupLedger is the GROUP BY: rows summed per the key columns of by, each type the SUM over the rows that reported it and unknown when none did -- the fold's per-type rule.

type RedisLedger

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

RedisLedger is the ledger on the fleet Redis. It dials nothing itself: the caller opens the client, and Close closes it.

func DialLedger

func DialLedger(addr, user, password string) *RedisLedger

DialLedger opens a client on addr (host:port) as the ACL user with its password ("" for the default user, "" for no password). The fleet Redis has its default user off, so a seat's password without its user is WRONGPASS. It silences go-redis's own logger first: a dial failure otherwise prints the library's untyped, local-time "connection pool: failed to dial after 5 attempts" lines to the process's stderr ahead of the verb's one typed FAILED line. The error they carry is not lost: it is the error the first command returns, which the verb prints.

func NewRedisLedger

func NewRedisLedger(rdb *redis.Client) *RedisLedger

NewRedisLedger wraps a client the caller opened.

func (*RedisLedger) Client

func (s *RedisLedger) Client() *redis.Client

Client returns the underlying redis.Client.

func (*RedisLedger) Close

func (s *RedisLedger) Close() error

Close closes the client.

func (*RedisLedger) LedgerReport

func (s *RedisLedger) LedgerReport(ctx context.Context, month, by string) ([]LedgerTotal, int, int, error)

LedgerReport reads every day hash of the month in one pipelined round trip and groups it. A field or value that does not decode is an error naming its key, never a skipped row. It returns the totals, how many calendar-day keys existed (indexed), and how many did not (missing).

func (*RedisLedger) Ping

func (s *RedisLedger) Ping(ctx context.Context) error

Ping is one PING, so a verb names an unreachable store before it reads any file.

func (*RedisLedger) ReplaceLedgerDay

func (s *RedisLedger) ReplaceLedgerDay(ctx context.Context, day string, entries []LedgerEntry) error

ReplaceLedgerDay swaps one day's rows by delegating to ReplaceLedgerDays.

func (*RedisLedger) ReplaceLedgerDays

func (s *RedisLedger) ReplaceLedgerDays(ctx context.Context, days []LedgerDay) error

ReplaceLedgerDays replaces a batch in one isolated EVAL round trip. It validates key types and mutation/restore permissions before deleting any day, and bounds each HSET's argument count. A recoverable mutation error restores prior hash contents; restoration itself still needs a working server and available memory. Redis does not automatically roll back scripts or provide crash recovery here. A server without redis.acl_check_cmd is refused before any mutation.

Jump to

Keyboard shortcuts

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