Documentation
¶
Index ¶
- type CutOver
- func (c *CutOver) Run(ctx context.Context) error
- func (c *CutOver) SetChecksUnderLock(fn func(ctx context.Context) error)
- func (c *CutOver) SetCutoverWithResult(fn CutoverResultCallback)
- func (c *CutOver) SetPostSwitch(fn func(ctx context.Context) error)
- func (c *CutOver) SetPreSwitch(fn func(ctx context.Context) error)
- type CutOverSource
- type CutoverResult
- type CutoverResultCallback
- type Move
- type ReverseFeed
- type ReverseFeedConfig
- type ReverseSource
- type Runner
- func (r *Runner) Abort(cause error)
- func (r *Runner) Cancel()
- func (r *Runner) Close() error
- func (r *Runner) DumpCheckpoint(ctx context.Context) error
- func (r *Runner) Progress() status.Progress
- func (r *Runner) Result() status.WorkflowResult
- func (r *Runner) Run(ctx context.Context) (retErr error)
- func (r *Runner) SetCutover(cutover func(ctx context.Context) error)
- func (r *Runner) SetCutoverWithResult(cutover CutoverResultCallback)
- func (r *Runner) SetLogger(logger *slog.Logger)
- func (r *Runner) SetMetricsSink(sink metrics.Sink)
- func (r *Runner) SetReverseCutover(fn func(ctx context.Context) error)
- func (r *Runner) SetReverseCutoverWithResult(fn CutoverResultCallback)
- func (r *Runner) Status() string
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CutOver ¶
type CutOver struct {
// contains filtered or unexported fields
}
func NewCutOver ¶
func NewCutOver(sources []CutOverSource, cutoverFunc func(ctx context.Context) error, dbConfig *dbconn.DBConfig, logger *slog.Logger) (*CutOver, error)
NewCutOver creates a new CutOver that handles multiple sources.
func (*CutOver) SetChecksUnderLock ¶ added in v0.18.0
SetChecksUnderLock registers checks to run under the source locks after the final flush and before the traffic switch. See CutOver.checksUnderLock.
func (*CutOver) SetCutoverWithResult ¶ added in v0.17.0
func (c *CutOver) SetCutoverWithResult(fn CutoverResultCallback)
SetCutoverWithResult installs a result-bearing forward cutover callback. It is mutually exclusive with the legacy error-only callback.
func (*CutOver) SetPostSwitch ¶ added in v0.16.0
SetPostSwitch registers a hook to run once under the source locks, after the traffic switch and before the source rename. See CutOver.postSwitch.
type CutOverSource ¶ added in v0.13.0
CutOverSource holds per-source state needed for the cutover.
type CutoverResult ¶ added in v0.17.0
CutoverResult reports authoritative evidence from a caller-owned cutover callback, including failures after a durable mutation and failures whose ownership outcome cannot be determined.
type CutoverResultCallback ¶ added in v0.17.0
type CutoverResultCallback func(context.Context) (CutoverResult, error)
CutoverResultCallback is the result-bearing cutover callback form.
A cutover callback (this form or the plain one passed to SetCutover or SetReverseCutover) runs while the move holds LOCK TABLES on sessions it sends no statements on. The final flush of the change feeds and the callback together must complete within 10 minutes, the wait_timeout spirit sets on every connection. Otherwise MySQL closes the idle lock sessions and releases the locks before the tables are renamed, and writes can reach the tables the traffic switch moved away from.
type Move ¶
type Move struct {
// Common holds the flags shared with migrate and sync: thread counts
// (--write-threads is per target), --max-connections (each source and
// target pool; dedicated monitor/advisory pools are separate),
// --max-commit-latency (any target), autoscaling (the busiest target host
// scales every shard together), TLS and --checkpoint-max-age.
flags.Common
// Cutover holds the flags shared with migrate: lock timeouts and
// --defer-cutover (the sentinel lives on the first target).
flags.Cutover
SourceDSN string `name:"source-dsn" help:"Where to copy the tables from." default:"spirit:spirit@tcp(127.0.0.1:3306)/src"`
TargetDSN string `name:"target-dsn" help:"Where to copy the tables to." default:"spirit:spirit@tcp(127.0.0.1:3306)/dest"`
DeferSecondaryIndexes bool `` /* 140-byte string literal not displayed */
// Force makes the runner wipe the target tables and start the copy fresh when
// it cannot resume from a checkpoint (e.g. the checkpoint is from an
// incompatible spirit version, or the target is in a state resume can't
// validate). Without it, an unresumable non-empty target is a hard error.
Force bool `` /* 152-byte string literal not displayed */
// ReverseWindow, when > 0, keeps the move alive after cutover in change-only
// reverse mode (targets→source) for this long, so the move can be rolled back
// before the source is retired. 0 (the default) is a normal cutover. During
// the window the source's now-retired _old tables are kept current from the
// targets; an operator rolls back by creating the _spirit_move_revert table on
// the first target (see revertmarker.go), otherwise the window elapses and the
// move finalizes forward. A sharded (multi-DSN) source additionally requires
// ReverseShardingProvider and SourceKeyRanges so the reverse feed can route
// rows back to the correct source shard — see the guard in Runner.Run. The
// data plane is ReverseFeed (reversefeed.go); the post-cutover driver is
// reverseWindow (reversewindow.go).
ReverseWindow time.Duration `` /* 166-byte string literal not displayed */
// SourceTables optionally specifies a list of tables to move.
// If empty, all tables in the source database will be moved.
// This is useful for Vitess MoveTables operations where only specific tables should be moved.
SourceTables []string
// ShardingProvider optionally provides vindex metadata for resharding operations.
// If nil, tables will not have vindex configuration (suitable for simple MoveTables 1:1 operations).
// For resharding operations (1:many), this should be set to provide sharding key information.
// The provider is called during table discovery to configure ShardingColumn and HashFunc
// on each TableInfo.
// SourceDSNs optionally specifies multiple source DSNs for N:M resharding operations.
// When set, each DSN represents a separate source shard. All sources must have identical
// table schemas. If empty, SourceDSN is used as the single source.
SourceDSNs []string `kong:"-"`
// SourceKeyRanges optionally specifies each source shard's Vitess-style key
// range ("-80", "80-", ...), parallel to SourceDSNs (SourceKeyRanges[i] is
// SourceDSNs[i]'s range). Required, together with ReverseShardingProvider,
// when ReverseWindow > 0 and the source is sharded (len(SourceDSNs) > 1):
// the reverse feed routes rows flowing back from the targets to the source
// shard whose range contains the row's hash. Unused otherwise.
SourceKeyRanges []string `kong:"-"`
ShardingProvider table.ShardingMetadataProvider `kong:"-"`
// ReverseShardingProvider provides the SOURCE keyspace's sharding metadata
// (vindex column + hash) for the reverse feed of a reverse-window move with
// a sharded source. It is consulted for each moved table when the window
// opens; a table without metadata is a hard error there, because reverse
// writes could not be routed to a source shard. Note the asymmetry with
// ShardingProvider, which describes the TARGET keyspace for the forward copy.
ReverseShardingProvider table.ShardingMetadataProvider `kong:"-"`
Targets []applier.Target `kong:"-"`
}
func (*Move) Validate ¶ added in v0.15.0
Validate is called by Kong after parsing to check for invalid flag values. Zero values mean "use the default" (NewRunner fills them in), so they are not rejected here; only explicitly-negative or otherwise invalid values are caught. Mirrors migration.Migration.Validate.
type ReverseFeed ¶ added in v0.16.0
type ReverseFeed struct {
// contains filtered or unexported fields
}
ReverseFeed is a running change-only reverse feed: one change.Source per ReverseSource, all sharing a single applier that writes to U (mirrors the forward move, where N sources share one applier).
func NewReverseFeed ¶ added in v0.16.0
func NewReverseFeed(ctx context.Context, cfg ReverseFeedConfig) (_ *ReverseFeed, err error)
NewReverseFeed wires the feeds and their shared applier. It does not open any binlog stream — call Start for that — but it does query each source server once: change.NewAutoClient selects (and validates) the change-source coordinate scheme per source, so e.g. a GTID-set Position on a server that no longer has GTIDs enabled fails here with a clear error rather than as a stream failure at Start.
func (*ReverseFeed) AllChangesFlushed ¶ added in v0.17.0
func (rf *ReverseFeed) AllChangesFlushed() bool
AllChangesFlushed reports whether every feed has applied its whole buffer.
Flush returning nil is not the same question, and callers that are about to discard the buffer must ask this one instead. A drain may decline to finish — lock contention it could not resolve in its budget, or a drain cut short to bound how long it holds the flush mutex — and reports that by leaving the changes buffered rather than by erroring, because for the periodic flusher "try again next tick" is the right response and failing the whole change is not. Flush's own loop compounds it: it exits once the backlog is merely *trivial*, not empty, so a residual below that threshold returns nil by design.
Mirrors the forward cutover's check in cutover.go, which pairs the two calls for exactly this reason.
func (*ReverseFeed) Close ¶ added in v0.16.0
func (rf *ReverseFeed) Close()
Close stops periodic flush and closes all feeds. Safe to call more than once. The applier is never Started (the subscription apply path is synchronous), so there is nothing to Stop on it.
func (*ReverseFeed) Err ¶ added in v0.16.0
func (rf *ReverseFeed) Err() error
Err returns the first fatal feed error, if any.
func (*ReverseFeed) Flush ¶ added in v0.16.0
func (rf *ReverseFeed) Flush(ctx context.Context) error
Flush drains all feeds synchronously (e.g. before a health check or a reverse cutover, so U reflects everything written to the sources so far).
func (*ReverseFeed) Positions ¶ added in v0.16.0
func (rf *ReverseFeed) Positions() []string
Positions returns each source's current safe-to-resume position, in the same order as the configured sources. Intended for the caller's checkpoint so the window can resume in reverse mode after a restart.
type ReverseFeedConfig ¶ added in v0.16.0
type ReverseFeedConfig struct {
Sources []ReverseSource
// Target is the U side when the former move source was a single database.
// Target.DB's default database MUST be U's schema (see ReverseSource.DB).
// Mutually exclusive with Targets.
Target applier.Target
// Targets is the U side when the former move source was SHARDED: one entry
// per former source shard, each with its Vitess-style key range set. Rows
// are routed by the WATCHED table's sharding metadata, so every
// ReverseSource table must have ShardingColumn and HashFunc set (the source
// keyspace's vindex) — NewReverseFeed fails otherwise. Each Targets[i].DB's
// default database MUST be that shard's schema (see ReverseSource.DB).
// Mutually exclusive with Target.
Targets []applier.Target
// TargetTables maps each watched (reverse-source) table NAME to the U-side
// TableInfo it is written to, built on Target.DB (with Targets, on any one
// shard: the schemas are identical and the name is unqualified, so each
// shard's own connection determines where the write lands). It is a map,
// not a slice, because the names can differ: after a forward cutover the
// source tables are renamed to their _old form, so a watched "t1" is
// written to "t1_old".
TargetTables map[string]*table.TableInfo
Logger *slog.Logger
DBConfig *dbconn.DBConfig
Threads int // applier write threads; 0 => default (4)
FlushInterval time.Duration // 0 => change.DefaultFlushInterval
}
ReverseFeedConfig configures a ReverseFeed.
type ReverseSource ¶ added in v0.16.0
type ReverseSource struct {
DB *sql.DB // connection to S (default DB == its schema)
Addr string // host:port for the binlog syncer
User string // binlog syncer user
Password string // binlog syncer password
Tables []*table.TableInfo // S-side tables to watch, built on DB
// Position is the opaque change.Source position to resume from: the one
// captured at cutover, or on a resumed window the feed's flushed position
// as last checkpointed during the window (see
// reverseWindow.checkpointPositions). Empty means start from the source's
// current head. Its encoding
// also selects the change-source coordinate scheme, exactly like a
// checkpoint resume (see change.NewAutoClient): a GTID set resumes through
// the GTID client (and requires the server to still have GTIDs enabled), a
// file:offset position through the binlog client, and the empty head-start
// case probes the server so the scheme matches what a cutover capture on
// that server would have produced.
Position string
}
ReverseSource is one reverse source: a former move target (shard S) whose binlog is tailed to keep the former move source (U) current.
DB's default database MUST be this source's schema. table.TableInfo.SetInfo resolves columns via information_schema WHERE table_schema=DATABASE() — the connection's default database, not the SchemaName argument — so a connection defaulting to the wrong schema silently loads the wrong table's definition, surfacing only at apply time as a fatal column-count mismatch.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
func (*Runner) Abort ¶ added in v0.18.0
Abort stops a running move with cause (see status.Aborter). The checkpoint dumper calls it when it cannot write a checkpoint, so Run returns the write error instead of context.Canceled.
func (*Runner) Cancel ¶
func (r *Runner) Cancel()
Cancel stops a running move. It is an operator cancellation: Run returns context.Canceled.
func (*Runner) DumpCheckpoint ¶
DumpCheckpoint is called approximately every minute. It writes the current state of the migration to the checkpoint table, which can be used in recovery. Previously resuming from checkpoint would always restart at the copier, but it can now also resume at the checksum phase.
func (*Runner) Result ¶ added in v0.17.0
func (r *Runner) Result() status.WorkflowResult
Result returns correctness evidence retained from the most recent Run invocation. It is intentionally separate from phase metrics.
func (*Runner) SetCutover ¶
SetCutover installs the caller-owned forward traffic switch. It runs under the source table locks and, together with the final flush, must complete within 10 minutes (see CutoverResultCallback).
func (*Runner) SetCutoverWithResult ¶ added in v0.17.0
func (r *Runner) SetCutoverWithResult(cutover CutoverResultCallback)
SetCutoverWithResult installs a result-bearing forward cutover callback. It is mutually exclusive with SetCutover; the most recent setter wins.
func (*Runner) SetMetricsSink ¶ added in v0.17.0
SetMetricsSink installs the destination for this run's metrics, including the workflow phase transitions reported by status.Tracker. It must be called before Run; a nil sink is ignored.
func (*Runner) SetReverseCutover ¶ added in v0.16.0
SetReverseCutover registers the legacy rollback traffic switch used if a revert is requested during the reverse window. It runs under the target table locks and, together with the reverse feed's final flush and the source renames, must complete within 10 minutes (see CutoverResultCallback).
func (*Runner) SetReverseCutoverWithResult ¶ added in v0.17.0
func (r *Runner) SetReverseCutoverWithResult(fn CutoverResultCallback)
SetReverseCutoverWithResult installs the result-bearing reverse cutover callback. It is mutually exclusive with SetReverseCutover.