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
- func CheckQuery(query string) error
- func Diff(a, b Fingerprint) []string
- func Run(ctx context.Context, root string, argv, env []string, log io.Writer) error
- type Command
- func (c *Command) Close() error
- func (c *Command) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)
- func (c *Command) Name() string
- func (c *Command) Partial() bool
- func (c *Command) Restore(ctx context.Context, _ []string) error
- func (c *Command) Rows(context.Context, []string) (Rows, error)
- func (c *Command) Seed(context.Context) error
- type Component
- type Fingerprint
- type Formatter
- type MySQL
- func (m *MySQL) Close() error
- func (m *MySQL) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)
- func (m *MySQL) FingerprintAs(ctx context.Context, format int, items []string) (Fingerprint, error)
- func (m *MySQL) Mode() string
- func (m *MySQL) Name() string
- func (m *MySQL) Partial() bool
- func (m *MySQL) Query(ctx context.Context, query string) ([]string, error)
- func (m *MySQL) Restore(ctx context.Context, items []string) error
- func (m *MySQL) Reused() bool
- func (m *MySQL) Rows(ctx context.Context, items []string) (Rows, error)
- func (m *MySQL) Seed(ctx context.Context) error
- type Options
- type Postgres
- func (p *Postgres) Close() error
- func (p *Postgres) Fingerprint(ctx context.Context, items []string) (Fingerprint, error)
- func (p *Postgres) FingerprintAs(ctx context.Context, format int, items []string) (Fingerprint, error)
- func (p *Postgres) Name() string
- func (p *Postgres) Partial() bool
- func (p *Postgres) Query(ctx context.Context, query string) ([]string, error)
- func (p *Postgres) Restore(ctx context.Context, items []string) error
- func (p *Postgres) Rows(ctx context.Context, items []string) (Rows, error)
- func (p *Postgres) Seed(ctx context.Context) error
- type Querier
- type RowChange
- type Rows
Constants ¶
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 ¶
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 ¶
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 ¶
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) Fingerprint ¶
Fingerprint hashes the output of the fingerprint command as one item named after the component.
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 ¶
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 (*MySQL) Fingerprint ¶
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 ¶
FingerprintAs hashes items of the working database as a fingerprint of the given format made them (Formatter).
func (*MySQL) Seed ¶
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 ¶
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) Fingerprint ¶
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) Query ¶
Query runs a read-only query (see CheckQuery) on the pristine database, which accepts connections only for that moment.
func (*Postgres) Seed ¶
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 ¶
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.