usage

package
v1.0.7 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CurrentDate

func CurrentDate() string

CurrentDate returns today's date as a string in YYYY-MM-DD format.

Types

type AccountClass added in v1.0.0

type AccountClass string

AccountClass classifies an account for metering/billing/analytics. It is the single source of truth read by the metering gate (see RecordAndCheck), kept orthogonal to the paid plan/tier. Mirrors the CHECK constraint in migrations/037_account_class.sql.

const (
	// ClassStandard is a real customer: metered, billed, counted in analytics.
	// The default for every account.
	ClassStandard AccountClass = "standard"
	// ClassInternal is internal dogfooding.
	ClassInternal AccountClass = "internal"
	// ClassSystem is synthetic-monitoring probe traffic.
	ClassSystem AccountClass = "system"
	// ClassDemo is a demo account.
	ClassDemo AccountClass = "demo"
)

type LiveUsageTracker

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

LiveUsageTracker is the real implementation backed by the billing store.

func NewUsageTracker

func NewUsageTracker(store *Store) *LiveUsageTracker

func (*LiveUsageTracker) RecordAndCheck

func (t *LiveUsageTracker) RecordAndCheck(ctx context.Context, userID, agentID, domain, direction string) (bool, error)

type MeteringPolicy added in v1.0.0

type MeteringPolicy struct {
	Meter     bool // record usage_events + usage_summaries (and thus count against quota)
	Bill      bool // include in billing
	Analytics bool // include in product analytics
}

MeteringPolicy is the resolved decision for an account class. Resolved once at the metering gate rather than re-derived at each write path.

func PolicyFor added in v1.0.0

func PolicyFor(c AccountClass) MeteringPolicy

PolicyFor returns the metering policy for an account class. Only standard accounts are metered/billed/analyzed; every non-standard class (internal, system, demo) is excluded on all three axes. An unknown/empty value fail-closed defaults to standard so a misclassified account is never silently exempted from billing.

type NoopUsageTracker

type NoopUsageTracker struct{}

NoopUsageTracker always allows everything. Used when billing is disabled.

func NewNoopUsageTracker

func NewNoopUsageTracker() *NoopUsageTracker

func (*NoopUsageTracker) RecordAndCheck

func (t *NoopUsageTracker) RecordAndCheck(ctx context.Context, userID, agentID, domain, direction string) (bool, error)

type Store

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

func NewStore

func NewStore(pool *pgxpool.Pool) *Store

func (*Store) CountAgentsByUser

func (s *Store) CountAgentsByUser(ctx context.Context, userID string) (int, error)

func (*Store) CountDomainsByUser added in v0.3.0

func (s *Store) CountDomainsByUser(ctx context.Context, userID string) (int, error)

CountDomainsByUser returns the number of domains owned by the user. Used by the limits enforcer to check max_domains caps. Counts every row in domains regardless of verification status; an unverified domain still consumes a slot until the user deletes it.

func (*Store) GetAccountClass added in v1.0.0

func (s *Store) GetAccountClass(ctx context.Context, userID string) (AccountClass, error)

GetAccountClass returns the account class for a user. A missing user (no row) resolves to ClassStandard so the metering gate fails toward metering — a real customer must never be silently exempted from billing because of a transient lookup miss. The PK lookup on users is cheap; account class is read once per metered message.

func (*Store) GetStorageBytes added in v0.3.0

func (s *Store) GetStorageBytes(ctx context.Context, userID string) (int64, error)

GetStorageBytes returns the user's current materialized storage bytes from account_usage. Returns 0 with no error if the user has no row yet — the trigger in migration 016 lazily creates the row on first message insert, so a pre-message user legitimately has 0 storage.

func (*Store) GetUsageSummary

func (s *Store) GetUsageSummary(ctx context.Context, userID, bucketDate string) (*UsageSummary, error)

func (*Store) IncrementUsageSummary

func (s *Store) IncrementUsageSummary(ctx context.Context, userID, bucketDate, direction string) error

func (*Store) MessagesThisMonth added in v0.3.0

func (s *Store) MessagesThisMonth(ctx context.Context, userID string) (int, error)

MessagesThisMonth returns the user's inbound+outbound message count for the current UTC calendar month, summed from usage_summaries. Returns 0 with no error if the user has no rows yet. The reference is time.Now().UTC() so server clocks crossing midnight UTC roll the counter consistently with the daily bucket_date written by IncrementUsageSummary.

func (*Store) RecordUsageEvent

func (s *Store) RecordUsageEvent(ctx context.Context, event *UsageEvent) error

type UsageEvent

type UsageEvent struct {
	ID        string    `json:"id"`
	UserID    string    `json:"user_id"`
	AgentID   string    `json:"agent_id"`
	Domain    string    `json:"domain"`
	Direction string    `json:"direction"`
	EventType string    `json:"event_type"`
	CreatedAt time.Time `json:"created_at"`
}

type UsageSummary

type UsageSummary struct {
	UserID        string `json:"user_id"`
	BucketDate    string `json:"bucket_date"`
	InboundCount  int    `json:"inbound_count"`
	OutboundCount int    `json:"outbound_count"`
	TotalCount    int    `json:"total_count"`
}

type UsageTracker

type UsageTracker interface {
	// RecordAndCheck records a usage event. Always returns true.
	RecordAndCheck(ctx context.Context, userID, agentID, domain, direction string) (allowed bool, err error)
}

UsageTracker records usage events. Always allows the action (no quota enforcement).

Jump to

Keyboard shortcuts

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