fleetbucket

package
v0.41.8 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package fleetbucket paces the calls a pod makes to Rivian when it takes vehicles over (zero-impact deploys, G7). A roll moves every group within seconds; the 50 ms stagger spaces one process's first connects, but N pods and N vehicles together still arrive as a burst. Wait gives each call a slot: first from a per-process token bucket, then from a fleet-wide per-second budget in Redis, with active vehicles (driving or charging) kept ahead of idle ones. A wait is bounded, so pacing never becomes an outage: after maxWait the call goes ahead and is counted as starved. A Redis that cannot answer means only the local bucket applies.

The fleet budget is a counter, not pub/sub: the app's Valkey user has no channel rights, and scripts plus TIME are allowed. Its seconds are Redis's (TIME, read inside the admission script), not any pod's: pods whose clocks disagree still count each call in the same second, and no pod's clock names a key.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bucket

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

Bucket is safe for concurrent use.

func New

func New(cfg Config) *Bucket

New builds a Bucket.

func (*Bucket) Wait

func (b *Bucket) Wait(ctx context.Context, class, shareKey string, active bool) Result

Wait blocks until the call may start. class names the call (for the caller's metrics); shareKey, when not empty, lets the calls of one Rivian session's shared socket count once. It returns when ctx is done too (Waited then says how long it waited; the caller checks ctx).

type Config

type Config struct {
	// LocalRPS and FleetRPS are the calls per second one process and the whole fleet may start. Defaults 10 and 20 (no Rivian 429 data yet: raise
	// them only from observed 429s and the takeover p95). FleetRPS is the TOTAL for active and idle calls together; idle calls may use at most
	// half of it, so active ones always find the other half.
	LocalRPS int
	FleetRPS int
	// ActiveMaxWait and IdleMaxWait bound one Wait. Active vehicles must not wait long; idle ones may queue.
	ActiveMaxWait time.Duration
	IdleMaxWait   time.Duration
	// ShareTTL: calls with the same share key (one Rivian session's socket) within this long of a granted one go through without a slot.
	ShareTTL time.Duration
	// RedisBackoff: after a Redis error the fleet budget is skipped (local only) for this long, so a Redis that does not answer costs one slow call, not every one.
	// Default 10 s.
	RedisBackoff time.Duration
	// Redis and Prefix: the fleet budget. Nil Redis: local only.
	Redis  *redis.Client
	Prefix string
	// Now is the clock and Sleep the wait for the next second of the fleet budget (tests drive both, so nothing depends on how loaded the
	// machine is). Sleep returns when d has passed or ctx is done. Now paces the local bucket, the share window and the Redis backoff; the fleet
	// budget's seconds are Redis's own.
	Now   func() time.Time
	Sleep func(ctx context.Context, d time.Duration)
	// Observe hears the outcome of every Wait (class and priority as the caller gave them): how long it waited, and whether it was shared,
	// starved or local-only. It is called once per Wait, on the caller's goroutine, and must not block.
	Observe func(class string, active bool, r Result)
}

Config sizes a Bucket. Zero values fall back to the defaults below.

type Result

type Result struct {
	Waited  time.Duration
	Starved bool // the bound passed and the call went ahead without a slot
	Shared  bool // a call with the same share key was granted recently: no slot used
	Local   bool // Redis did not answer: the fleet budget was skipped
	// FleetSecond is the Unix second, by Redis's clock, whose fleet budget granted the call (0: no fleet slot was granted).
	FleetSecond int64
}

Result says what a Wait did.

Jump to

Keyboard shortcuts

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