Help us shape the future of Go! Take the 2026 Go Developer Survey

state

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package state restores the data an application runs on and fingerprints it, so every capture starts from the same state and every change a request makes to the data is seen. A component is one part of that state: a MySQL/MariaDB or PostgreSQL database with a pristine copy, or anything else through restore and fingerprint commands.

Index

Constants

View Source
const FingerprintFormat = 2

FingerprintFormat numbers the way fingerprints are made; a fingerprint recorded in another format (a pristine copy's, a baseline's) can differ from a new one of the same data. 2: MySQL/MariaDB triggers and views include the collation they were made with; PostgreSQL adds functions, enum, domain and composite types, schemas, materialized views, and to a table's definition row security, policies, rules, privileges, comments, column collations, UNLOGGED and the replica identity, to a view's its rules and privileges, to a sequence its parameters and the value setval(…, false) left. Items that did not change keep their hash, so a database without such objects fingerprints as before.

Variables

This section is empty.

Functions

func CheckQuery

func CheckQuery(query string) error

CheckQuery accepts a single read-only SELECT or WITH statement.

func Diff

func Diff(a, b Fingerprint) []string

Diff lists the items whose hash differs or that exist on one side only.

func Run

func Run(ctx context.Context, root string, argv, env []string, log io.Writer) error

Run runs a command of the project without a shell, from root, with env added to its environment (procx: a time limit or an interrupt stops what it started too). Its output is shown only when it fails (the last lines), so a working restore or migration does not fill the report with its own messages; only the end of it is kept.

Types

type Command

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

Command is a component handled entirely by commands of the project.

func NewCommand

func NewCommand(name, root string, restore, fingerprint, env []string, log io.Writer) *Command

NewCommand returns a command component. Commands run from root, without a shell, with env added to their environment; their output goes to log.

func (*Command) Close

func (c *Command) Close() error

func (*Command) Fingerprint

func (c *Command) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)

Fingerprint hashes the output of the fingerprint command as one item named after the component.

func (*Command) Name

func (c *Command) Name() string

func (*Command) Partial

func (c *Command) Partial() bool

func (*Command) Restore

func (c *Command) Restore(ctx context.Context, _ []string) error

func (*Command) Rows

func (c *Command) Rows(context.Context, []string) (Rows, error)

func (*Command) Seed

func (c *Command) Seed(context.Context) error

type Component

type Component interface {
	// Name is the component's name in driftgate.yaml.
	Name() string
	// Fingerprint hashes the working state; with items set, only those
	// items. A component that cannot fingerprint returns nil.
	Fingerprint(ctx context.Context, items []string) (Fingerprint, error)
	// Restore brings the given items of the working state back to the
	// pristine copy; nil means everything. A command component always
	// restores everything.
	Restore(ctx context.Context, items []string) error
	// Seed makes the current working state the new pristine copy.
	Seed(ctx context.Context) error
	// Rows reads the rows of the tracked tables among items; nil means all
	// tracked tables.
	Rows(ctx context.Context, items []string) (Rows, error)
	// Partial reports whether Restore can restore single items.
	Partial() bool
	Close() error
}

Component is one part of the state.

type Fingerprint

type Fingerprint map[string]string

Fingerprint maps the items of a component (tables, views, triggers, sequences) to a hash of their definition and content.

func (Fingerprint) Merge

func (f Fingerprint) Merge(g Fingerprint) Fingerprint

Merge returns f with the hashes of g written over it.

func (Fingerprint) Subset

func (f Fingerprint) Subset(items []string) Fingerprint

Subset returns the part of f for the given items; an item f does not have is left out.

type Formatter

type Formatter interface {
	FingerprintAs(ctx context.Context, format int, items []string) (Fingerprint, error)
}

Formatter is a component that can fingerprint items as an older format (1) made them, so a fingerprint recorded in that format can be compared with the data now (verify --migrate-state).

type MySQL

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

MySQL is a MySQL or MariaDB database. The pristine copy is a second database on the same server, and a restore copies back only the tables, views, sequences and triggers that differ. Routines and events are not tracked; system-versioned tables must be excluded.

func NewMySQL

func NewMySQL(o Options) (*MySQL, error)

NewMySQL connects to the server.

func (*MySQL) Close

func (m *MySQL) Close() error

func (*MySQL) Fingerprint

func (m *MySQL) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)

Fingerprint hashes the working database. A full fingerprint first reads the server's write counters: when none moved since the last full fingerprint, no table can have changed, and only the items the counters do not cover (sequences, tables of other engines) are read again. When only rows were written, the per-table counters (see tableCounters) name the tables to checksum again; anything else reads every table.

func (*MySQL) FingerprintAs

func (m *MySQL) FingerprintAs(ctx context.Context, format int, items []string) (Fingerprint, error)

FingerprintAs hashes items of the working database as a fingerprint of the given format made them (Formatter).

func (*MySQL) Mode

func (m *MySQL) Mode() string

Mode says how the last full fingerprint knew which tables to read.

func (*MySQL) Name

func (m *MySQL) Name() string

func (*MySQL) Partial

func (m *MySQL) Partial() bool

func (*MySQL) Query

func (m *MySQL) Query(ctx context.Context, query string) ([]string, error)

Query runs a read-only query (see CheckQuery) on the pristine database.

func (*MySQL) Restore

func (m *MySQL) Restore(ctx context.Context, items []string) error

func (*MySQL) Reused

func (m *MySQL) Reused() bool

Reused reports whether the last fingerprint came from the write check.

func (*MySQL) Rows

func (m *MySQL) Rows(ctx context.Context, items []string) (Rows, error)

func (*MySQL) Seed

func (m *MySQL) Seed(ctx context.Context) error

Seed copies the working database into a new pristine database. Excluded tables are copied without rows, so views that use them still work. The mark (pristineTable) is made first, so a seed that stops halfway leaves a database the next seed may drop; DriftGate's record of the pristine fingerprint is removed before a seed (capture.Seed), so such a database is not taken for a pristine copy.

type Options

type Options struct {
	Name        string
	DSN         string
	Working     string   // database the application uses
	Pristine    string   // its pristine copy
	Exclude     []string // globs over table names; never fingerprinted or restored
	RowTracking []string // tables whose changed rows are recorded
	Log         io.Writer
	// Dial, when set, makes every connection to the server: only to an
	// allowed host (dbx.AllowDial).
	Dial dbx.DialFunc
	// AdoptPristine lets Seed replace a pristine database without the mark
	// of one it made: DriftGate's own record names it as the pristine copy
	// (made before the mark existed, by an earlier release).
	AdoptPristine bool
	// Replacing, when set, runs in Seed right before the pristine database
	// is dropped or renamed away, once the new copy may replace it.
	Replacing func() error
}

Options configure a database component.

type Postgres

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

Postgres is a PostgreSQL database. The pristine copy is a second database on the same server; a restore recreates the working database from it as a template, which PostgreSQL does by copying files, so it is fast even for a large database. PostgreSQL cannot read across databases, so a restore always covers the whole database (Partial is false).

func NewPostgres

func NewPostgres(o Options) (*Postgres, error)

NewPostgres connects to the server. The DSN is a postgres:// URL; its database (default postgres) is used only to create and drop databases.

func (*Postgres) Close

func (p *Postgres) Close() error

Close waits for the drop of the database the last copy replaced.

func (*Postgres) Fingerprint

func (p *Postgres) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)

Fingerprint hashes the working database. A working database that does not exist has no items, so a restore brings back every item of the pristine copy.

func (*Postgres) FingerprintAs

func (p *Postgres) FingerprintAs(ctx context.Context, format int, items []string) (Fingerprint, error)

FingerprintAs hashes items of the working database as a fingerprint of the given format made them (Formatter): format 1 had no row security, policies, rules, privileges, comments, column collations, UNLOGGED or replica identity in a table's definition, no rules or privileges in a view's, only the last value of a sequence, and no functions, types, schemas or materialized views.

func (*Postgres) Name

func (p *Postgres) Name() string

func (*Postgres) Partial

func (p *Postgres) Partial() bool

func (*Postgres) Query

func (p *Postgres) Query(ctx context.Context, query string) ([]string, error)

Query runs a read-only query (see CheckQuery) on the pristine database, which accepts connections only for that moment.

func (*Postgres) Restore

func (p *Postgres) Restore(ctx context.Context, items []string) error

func (*Postgres) Rows

func (p *Postgres) Rows(ctx context.Context, items []string) (Rows, error)

func (*Postgres) Seed

func (p *Postgres) Seed(ctx context.Context) error

Seed copies the working database into a new pristine database that does not accept connections, so nothing can change it or block a restore. The database it replaces must carry pristineComment, be empty, or be adopted (Options.AdoptPristine): any other database named as the pristine one is someone's data and is not dropped.

type Querier

type Querier interface {
	Query(ctx context.Context, query string) ([]string, error)
}

Querier runs a read-only query on the pristine copy and returns the first column of every row as text.

type RowChange

type RowChange struct {
	Table   string   `json:"table"`
	Key     string   `json:"key"`
	Change  string   `json:"change"` // inserted | deleted | updated
	Columns []string `json:"columns,omitempty"`
}

RowChange is one row of a tracked table that a request inserted, deleted or updated. Key is the primary key, written as column=value pairs.

func RowDiff

func RowDiff(before, after Rows) []RowChange

RowDiff lists the rows that differ between two reads of the same tables.

type Rows

type Rows map[string]map[string]map[string]string

Rows holds the rows of tracked tables: table → key → column → value hash.

Jump to

Keyboard shortcuts

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