billing

package
v1.108.26 Latest Latest
Warning

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

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

Documentation

Overview

fleet.go is the fleet-billing orchestrator — the ONE place the three connected- compute tiers are metered, all through the canonical commerce/metering path (service.NewMeteringClient), per org+project, so a customer sees ONE invoice however their compute is connected:

(a) BYOC cloud account  → 1% of the account's cloud spend (daily, incremental).
(b) BYO hardware/device → flat $1/mo per connected GPU/device (monthly).
(c) hanzo.network validator → FREE (verified on-chain; never billed).

The tier is a property of the compute source (a Provider vs a FleetWorker.Kind), resolved here; there is one debit path, three rates. Money safety: every unit is claimed cluster-wide via object BillingLease before it is billed, because visor runs replicas: 2 with no leader election and commerce does not dedup on requestId. Honesty: no spend or exemption is ever fabricated — an unreadable cost is skipped (no fee) and an unverified validator is billed (flagged), never the reverse.

Brand policy: the upstream cloud TYPE (AWS/DO/…) never leaves the cost readers; the metering line's Model carries only the tier and the customer's OWN provider/worker label, never an upstream provider name.

reporter.go is the recurring node-pool meter: every pool that is RUNNING is debited one hour of its resale price, every hour it runs, to the org that owns it.

It debits on the ONE compute meter — service.NewMeteringClient + RecordCompute, the same client, the same KMS-synced COMMERCE_SERVICE_TOKEN, the same POST /v1/billing/usage, the same X-Org-Id tenant header as every other debit in this binary. It used to have its own: its own credential (COMMERCE_TOKEN, a name nothing in production sets), its own HTTP client, its own path ({base}/api/v1/billing/meter-events — commerce serves no /api/ prefix), and no tenant header at all. Three independent reasons the same request could not have been billed, so a GPU pool ran free for every hour after its first.

A second meter is how that happens. There is one now.

WHAT IT BILLS FROM is the other half, and it changed for the same class of reason. The sweep used to read the DB row and nothing else — but the row's key is (Owner, Name), and the Name comes from the customer's own create body. A row a customer can name is a row a customer can collide with, delete, or leave stale, and each of those turns into free compute. The provider knows what it is actually running; the row does not. So for Hanzo's house account the PROVIDER is the authority and the row is a cache of it. See billableUnits.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BillWorkerOnConnect

func BillWorkerOnConnect(ctx context.Context, w *object.FleetWorker)

BillWorkerOnConnect arms billing for a freshly-connected worker — the "armed on connect" half of tier (b). It bills the current month immediately (idempotent per month via the same lease the monthly sweep uses), so a box connected mid-month is billed at once, and the monthly sweep never double-bills it.

func CollectBYOCCosts

func CollectBYOCCosts(ctx context.Context, now time.Time)

CollectBYOCCosts is the daily tier-(a) collector. For every org's active BYOC cloud provider it reads month-to-date spend via that cloud's cost API and meters 1% of the increment since the last run to org+project. No spend → no fee; an unreadable cost (unconfigured scope, transient error) is skipped for this run and recovered on the next (the cursor is only advanced on a successful read). Single-flight per (provider, day) via BillingLease, so replicas never double-bill.

func MeterConnectedDevices

func MeterConnectedDevices(ctx context.Context, now time.Time)

MeterConnectedDevices is the monthly tier-(b)/(c) sweep: bill every CONNECTED BYO worker $1/device for the current month (validators exempt). It is safe to run more than once a month — the per-(worker, month) lease makes each worker's fee exactly-once.

func MeterRunningNodePools added in v1.108.24

func MeterRunningNodePools(ctx context.Context, now time.Time)

MeterRunningNodePools debits every running node pool one hour of its resale price to its owning org — the node-pool half of the hourly money sweep, whose machine half is service.MeterRunningMachines.

It is driven by the ticker UNDER the same per-hour single-flight lease as the machine sweep (object.ClaimMeterHour), so a pool-hour is claimed once cluster-wide. It carries no lease of its own: two leases on the same hour key would have one sweep starve the other.

A NO from Billable is loud, never silent: an absent service token stops all revenue collection while the pools keep costing us money upstream.

Types

This section is empty.

Jump to

Keyboard shortcuts

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