fleet

package
v0.6.7 Latest Latest
Warning

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

Go to latest
Published: Jul 1, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package fleet manages many SQLite databases as a single unit: discovery from Turso orgs and Cloudflare D1 accounts, baseline capture, and parallel drift detection across the whole fleet.

Index

Constants

View Source
const DefaultConfigFile = "litescope.fleet.yaml"

DefaultConfigFile is the conventional fleet config name.

Variables

This section is empty.

Functions

func Hash

func Hash(s *schema.Schema) string

Hash returns a hex SHA-256 over a deterministic, drift-significant serialization of the schema. Order-independent: tables, columns, and indexes are all sorted so column/table declaration order does not affect the result.

func SendHealthAlert

func SendHealthAlert(webhookURL string, r *HealthReport) error

SendHealthAlert POSTs a fault summary to a webhook (Slack-compatible when the URL points at Slack, otherwise generic JSON). It is a no-op when the fleet is healthy. Used by scheduled/continuous health watch.

Types

type BlastGroup

type BlastGroup struct {
	Tag     string   `json:"tag"`     // shared tag, e.g. "group:prod"
	Total   int      `json:"total"`   // databases carrying this tag
	Faulted []string `json:"faulted"` // critically faulted members
	AtRisk  []string `json:"at_risk"` // healthy members of the same cohort
}

BlastGroup is a shared cohort (a tag, e.g. a Turso group) that contains at least one faulted database — so the rest of the cohort may be at risk from a shared-infrastructure problem.

func BlastRadius

func BlastRadius(dbs []Database, report *HealthReport) []BlastGroup

BlastRadius groups critically faulted databases by the tags they share, so a single fault report shows the blast radius across shared infrastructure (Turso groups, regions). Only cohorts containing a fault are returned, most faults first.

type CheckResult

type CheckResult struct {
	Database string `json:"database"`
	DSN      string `json:"dsn"`
	// State is one of: "ok", "drift", "no-baseline", "error".
	State    string               `json:"state"`
	Drift    *monitor.DriftResult `json:"drift,omitempty"`
	Err      error                `json:"-"`
	Error    string               `json:"error,omitempty"`
	Duration time.Duration        `json:"-"`
}

CheckResult is the drift outcome for a single fleet member.

type Config

type Config struct {
	Version      int        `yaml:"version"`
	Name         string     `yaml:"name,omitempty"`
	BaselinesDir string     `yaml:"baseline_dir,omitempty"` // default dir for captured baselines
	Databases    []Database `yaml:"databases"`
	// contains filtered or unexported fields
}

Config is a fleet definition, normally stored as litescope.fleet.yaml.

func Load

func Load(path string) (*Config, error)

Load reads a fleet config from disk.

func (*Config) Active

func (c *Config) Active() []Database

Active returns the databases that are not quarantined.

func (*Config) BaselineDir

func (c *Config) BaselineDir() string

BaselineDir returns the directory baselines are stored in (default: .litescope/baselines).

func (*Config) BaselinePath

func (c *Config) BaselinePath(db Database) string

BaselinePath returns the baseline path for a database, computing a default under BaselineDir when the entry doesn't specify one.

func (*Config) Filter

func (c *Config) Filter(tag string) []Database

Filter returns non-quarantined databases matching the given tag, or all non-quarantined databases when tag is "". Quarantined databases are excluded from every fleet operation until cleared.

func (*Config) Merge

func (c *Config) Merge(incoming []Database) (added, updated int)

Merge adds or updates databases by name, preserving existing baselines/tags when the incoming entry doesn't set them. Returns counts of added/updated.

func (*Config) Save

func (c *Config) Save(path string) error

Save writes the config to the given path (or its source path if empty).

func (*Config) SetQuarantine

func (c *Config) SetQuarantine(names []string, quarantined bool) int

SetQuarantine marks the named databases quarantined (or clears it) and returns how many entries changed.

type ConvergeClusterPlan

type ConvergeClusterPlan struct {
	ClusterID   string           `json:"cluster_id"`
	Members     []Database       `json:"-"`       // full entries so we have DSNs
	MemberNames []string         `json:"members"` // names, for JSON/display
	SQL         string           `json:"sql"`
	Statements  int              `json:"statements"`
	Destructive bool             `json:"destructive"` // drops a column/table on these DBs
	Drift       []diff.TableDiff `json:"drift,omitempty"`
}

ConvergeClusterPlan is the convergence work for one drifted schema cluster: the SQL that transforms every member into the canonical schema.

type ConvergePlan

type ConvergePlan struct {
	CanonicalID     string                `json:"canonical_id"`
	AlreadyOK       int                   `json:"already_ok"`        // databases already matching canonical
	Clusters        []ConvergeClusterPlan `json:"clusters"`          // drifted clusters needing convergence
	TotalToConverge int                   `json:"total_to_converge"` // total drifted databases
	Unreachable     []FingerprintError    `json:"unreachable,omitempty"`
}

ConvergePlan describes what it takes to bring every drifted database in the fleet back to the canonical schema.

func PlanConvergence

func PlanConvergence(dbs []Database, canonical *schema.Schema, concurrency int) (*ConvergePlan, error)

PlanConvergence fingerprints the fleet and, for every cluster that differs from canonical, generates the migration SQL to converge it. When canonical is nil, the largest cluster's schema is used as the reference.

func (*ConvergePlan) HasDestructive

func (p *ConvergePlan) HasDestructive() bool

HasDestructive reports whether converging any cluster would drop data.

type DBState

type DBState string

DBState is the outcome for one database in a rollout.

const (
	StateApplied DBState = "applied" // committed successfully
	StateDryRun  DBState = "dry-run" // validated, rolled back
	StateFailed  DBState = "failed"  // errored; halts the rollout
	StateSkipped DBState = "skipped" // not attempted (rollout halted earlier)
	StateCanary  DBState = "canary"  // not attempted (canary limit reached)
)

type Database

type Database struct {
	Name     string `yaml:"name"`
	DSN      string `yaml:"dsn"`
	Baseline string `yaml:"baseline,omitempty"` // path to the baseline snapshot
	// Tags allow grouping (e.g. region, tenant) for filtered operations.
	Tags []string `yaml:"tags,omitempty"`
	// Quarantined marks a database as excluded from fleet operations — set by
	// `fleet recover` when a faulted database cannot be restored.
	Quarantined bool `yaml:"quarantined,omitempty"`
}

Database is one member of a fleet.

func DiscoverD1

func DiscoverD1(accountID, token string) ([]Database, error)

DiscoverD1 lists every D1 database in a Cloudflare account and returns fleet entries with d1:// DSNs. The same API token is used for discovery and queries, so the returned DSNs are immediately usable.

func DiscoverTurso

func DiscoverTurso(org, platformToken, dbToken string) ([]Database, error)

DiscoverTurso lists every database in a Turso organization via the platform API and returns fleet entries with ready-to-use turso:// DSNs.

platformToken is an org/platform API token (https://api.turso.tech). dbToken is the database auth token applied to each entry's DSN; a group-level auth token works across the whole org. When dbToken is empty, the DSN is emitted with a TOKEN placeholder for the user to fill in.

type FingerprintCluster

type FingerprintCluster struct {
	ID          string           `json:"id"`              // short hash of the canonical schema serialization
	Count       int              `json:"count"`           // number of databases in this cluster
	Members     []string         `json:"members"`         // database names, sorted
	IsCanonical bool             `json:"is_canonical"`    // true for the reference cluster (largest by default)
	Drift       []diff.TableDiff `json:"drift,omitempty"` // how this cluster differs from canonical; nil for canonical
	// contains filtered or unexported fields
}

FingerprintCluster is a group of databases that share an identical schema.

type FingerprintError

type FingerprintError struct {
	Database string `json:"database"`
	Error    string `json:"error"`
}

FingerprintError records a database that could not be read.

type FingerprintReport

type FingerprintReport struct {
	Total       int                  `json:"total"`    // databases successfully fingerprinted
	Clusters    []FingerprintCluster `json:"clusters"` // canonical first, then by count desc
	Unreachable []FingerprintError   `json:"unreachable,omitempty"`
	CheckedAt   time.Time            `json:"checked_at"`
}

FingerprintReport is the result of fingerprinting an entire fleet.

func Fingerprint

func Fingerprint(dbs []Database, concurrency int) *FingerprintReport

Fingerprint reads every database's live schema in parallel and groups them into clusters of identical schemas. The largest cluster is marked canonical; every other cluster carries a diff describing how it differs from canonical.

The fingerprint is computed over exactly the fields the diff engine treats as drift-significant (table presence, column name/type/not-null, index presence), so two databases share a fingerprint if and only if `fleet check` would report no drift between them.

type FleetReport

type FleetReport struct {
	Results   []CheckResult `json:"results"`
	CheckedAt time.Time     `json:"checked_at"`
}

FleetReport aggregates per-database results.

func Check

func Check(cfg *Config, dbs []Database, concurrency int) *FleetReport

Check runs a drift check across every database in parallel, comparing each live schema against its baseline snapshot. concurrency <= 0 uses the default.

func (*FleetReport) Counts

func (r *FleetReport) Counts() (ok, drift, noBaseline, errCount int)

Counts returns how many databases fell into each state.

func (*FleetReport) HasProblems

func (r *FleetReport) HasProblems() bool

HasProblems reports whether any database drifted or errored.

type HealthReport

type HealthReport struct {
	Results   []HealthResult `json:"results"`
	CheckedAt time.Time      `json:"checked_at"`
}

HealthReport aggregates fleet-wide health, sorted worst-first.

func Health

func Health(dbs []Database, deep bool, concurrency int) *HealthReport

Health inspects every database in parallel for operational faults. Local files get the full inspection (integrity, WAL bloat, fragmentation, size); remote databases (Turso, D1) report reachability only, since file-level signals require local access.

func (*HealthReport) Counts

func (r *HealthReport) Counts() (ok, warning, critical int)

Counts tallies databases by severity.

func (*HealthReport) HasFaults

func (r *HealthReport) HasFaults() bool

HasFaults reports whether any database is in warning or critical state.

type HealthResult

type HealthResult struct {
	Database string         `json:"database"`
	DSN      string         `json:"dsn"`
	Report   *health.Report `json:"report"`
	Duration time.Duration  `json:"-"`
}

HealthResult is the operational health of one fleet member.

type RecoverOptions

type RecoverOptions struct {
	BackupDir  string // where to look for backups ("" = alongside each DB)
	DryRun     bool   // report what would happen without restoring or quarantining
	Deep       bool   // exhaustive integrity_check when assessing health
	Quarantine bool   // quarantine databases with no healthy backup
}

RecoverOptions controls a fleet recovery.

type RecoverReport

type RecoverReport struct {
	Results   []RecoverResult `json:"results"`
	DryRun    bool            `json:"dry_run"`
	StartedAt time.Time       `json:"started_at"`
}

RecoverReport aggregates a fleet recovery.

func Recover

func Recover(dbs []Database, opts RecoverOptions) *RecoverReport

Recover triages the fleet and restores every critically faulted local database from its most recent *verified-healthy* backup. Databases with no healthy backup are flagged for quarantine. Bloat/warning-level issues are not recovery targets and are reported as healthy here.

Recovery only applies to local files; a faulted remote database is reported as needing manual recovery. In dry-run mode nothing is written.

func (*RecoverReport) Counts

func (r *RecoverReport) Counts() (restored, quarantined, failed, healthy int)

Counts tallies databases by recovery outcome.

func (*RecoverReport) Quarantine

func (r *RecoverReport) Quarantine() []string

Quarantine returns the names of databases that should be marked quarantined.

type RecoverResult

type RecoverResult struct {
	Database   string        `json:"database"`
	DSN        string        `json:"dsn"`
	State      RecoverState  `json:"state"`
	BackupPath string        `json:"backup_path,omitempty"` // backup used to restore
	Detail     string        `json:"detail,omitempty"`
	Err        error         `json:"-"`
	Error      string        `json:"error,omitempty"`
	Duration   time.Duration `json:"-"`
}

RecoverResult is the per-database recovery record.

type RecoverState

type RecoverState string

RecoverState is the outcome of attempting to recover one database.

const (
	RecoverHealthy     RecoverState = "healthy"     // no fault — nothing to do
	RecoverRestored    RecoverState = "restored"    // restored from a verified backup
	RecoverQuarantined RecoverState = "quarantined" // faulted, no healthy backup — excluded from future ops
	RecoverFailed      RecoverState = "failed"      // recovery attempt errored
	RecoverRemote      RecoverState = "remote"      // remote DB faulted — needs manual recovery
)

type RolloutOptions

type RolloutOptions struct {
	DryRun    bool   // validate against every database without committing
	Canary    int    // stop after this many successful applies (0 = no canary)
	BackupDir string // where local backups are written ("" = alongside each DB)
	NoBackup  bool   // skip local backups (dry-run never backs up)
}

RolloutOptions controls a staged fleet migration.

type RolloutReport

type RolloutReport struct {
	Results   []RolloutResult `json:"results"`
	StartedAt time.Time       `json:"started_at"`
	DryRun    bool            `json:"dry_run"`
	Halted    bool            `json:"halted"` // true when a failure stopped the rollout
}

RolloutReport aggregates a staged migration across the fleet.

func Converge

func Converge(plan *ConvergePlan, opts RolloutOptions) *RolloutReport

Converge applies a convergence plan, staged and fail-closed: databases are migrated one at a time across all clusters, and the first failure halts the rollout so a bad convergence can't cascade. Reuses the same per-database safety pipeline as Rollout (backup, transaction, verification, restore).

In dry-run mode every database is validated (apply + rollback) and the run never halts early, so you see every database that would fail at once.

func Rollout

func Rollout(dbs []Database, sqlText string, opts RolloutOptions) *RolloutReport

Rollout applies a migration to each database in order, stopping at the first failure so a bad migration can't cascade across the fleet.

  • Local files use migrate.Apply: pre-flight integrity check, VACUUM INTO backup, single transaction, foreign-key + integrity verification, and automatic rollback/restore on failure.
  • Remote databases (Turso, D1) execute via their provider API. Turso runs transactionally; D1 cannot roll back a multi-statement batch.

In dry-run mode every database is validated (apply + rollback) and the rollout never halts early, so you see which databases would fail. Otherwise the first failure halts the rollout and the remaining databases are marked skipped.

func (*RolloutReport) Counts

func (r *RolloutReport) Counts() (applied, failed, skipped int)

Counts tallies databases by terminal state.

type RolloutResult

type RolloutResult struct {
	Database   string        `json:"database"`
	DSN        string        `json:"dsn"`
	State      DBState       `json:"state"`
	Executed   int           `json:"executed"`              // statements applied
	BackupPath string        `json:"backup_path,omitempty"` // local backup, if any
	Provider   string        `json:"provider"`              // local, turso, d1
	Err        error         `json:"-"`
	Error      string        `json:"error,omitempty"`
	Duration   time.Duration `json:"-"`
}

RolloutResult is the per-database record.

type SnapshotResult

type SnapshotResult struct {
	Database string
	Path     string
	Tables   int
	Err      error
}

SnapshotResult is the baseline-capture outcome for one database.

func Snapshot

func Snapshot(cfg *Config, dbs []Database, concurrency int) []SnapshotResult

Snapshot captures a baseline for every database in parallel, writing each to its configured baseline path. concurrency <= 0 uses the default.

Jump to

Keyboard shortcuts

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