Documentation
¶
Index ¶
- Constants
- Variables
- func CatalogDeltaFloorKey() []byte
- func CatalogDeltaKey(version uint64) []byte
- func CatalogDeltaVersionFromKey(key []byte) (uint64, bool)
- func CatalogNextRouteIDKey() []byte
- func CatalogNextSplitJobIDKey() []byte
- func CatalogRouteIDFromKey(key []byte) (uint64, bool)
- func CatalogRouteKey(routeID uint64) []byte
- func CatalogSplitJobHistoryKey(terminalAtMs int64, jobID uint64) []byte
- func CatalogSplitJobHistoryKeyParts(key []byte) (int64, uint64, bool)
- func CatalogSplitJobIDFromKey(key []byte) (uint64, bool)
- func CatalogSplitJobKey(jobID uint64) []byte
- func CatalogVersionKey() []byte
- func CloneBytes(b []byte) []byte
- func DecodeCatalogNextRouteID(raw []byte) (uint64, error)
- func DecodeCatalogNextSplitJobID(raw []byte) (uint64, error)
- func DecodeCatalogVersion(raw []byte) (uint64, error)
- func EncodeCatalogDelta(delta CatalogDelta) ([]byte, error)
- func EncodeCatalogNextRouteID(nextRouteID uint64) []byte
- func EncodeCatalogNextSplitJobID(nextJobID uint64) []byte
- func EncodeCatalogVersion(version uint64) []byte
- func EncodeRouteDescriptor(route RouteDescriptor) ([]byte, error)
- func EncodeRouteDescriptorForCatalogWrite(route RouteDescriptor, allowV2 bool) ([]byte, error)
- func EncodeRouteDescriptorForCatalogWriteWithSplitAtHLCOffset(route RouteDescriptor, allowV2 bool) ([]byte, uint64, error)
- func EncodeSplitJob(job SplitJob) ([]byte, error)
- func IsCatalogDeltaKey(key []byte) bool
- func IsCatalogRouteKey(key []byte) bool
- func IsCatalogSplitJobHistoryKey(key []byte) bool
- func IsCatalogSplitJobKey(key []byte) bool
- func IsMigrationKnownInternalKey(key []byte) bool
- func MigrationKnownInternalPrefixes() [][]byte
- func NextRouteIDFloor(routes []RouteDescriptor) (uint64, error)
- func NextSplitJobIDFloor(jobs []SplitJob) (uint64, error)
- func RunCatalogWatcher(ctx context.Context, catalog *CatalogStore, engine *Engine, ...) error
- func ValidateMigrationRouteRange(routeStart, routeEnd []byte) error
- type CatalogChangeSet
- type CatalogDelta
- type CatalogMigrationStoreResolver
- type CatalogMutationOp
- type CatalogRouteMutation
- type CatalogSnapshot
- type CatalogSnapshotObserver
- type CatalogStore
- func (s *CatalogStore) AllowsRouteDescriptorV2Writes() bool
- func (s *CatalogStore) BuildDeltaMutationsAt(ctx context.Context, readTS uint64, delta CatalogDelta) ([]*store.KVPairMutation, error)
- func (s *CatalogStore) ChangesSince(ctx context.Context, afterVersion uint64, limit int) (CatalogChangeSet, error)
- func (s *CatalogStore) CreateSplitJob(ctx context.Context, job SplitJob) error
- func (s *CatalogStore) DeleteSplitJob(ctx context.Context, jobID uint64) error
- func (s *CatalogStore) DeltaFloor(ctx context.Context) (uint64, error)
- func (s *CatalogStore) LatestCommitTS() uint64
- func (s *CatalogStore) ListSplitJobs(ctx context.Context) ([]SplitJob, error)
- func (s *CatalogStore) ListSplitJobsAt(ctx context.Context, ts uint64) ([]SplitJob, error)
- func (s *CatalogStore) MoveSplitJobToHistory(ctx context.Context, expected SplitJob, job SplitJob) error
- func (s *CatalogStore) NextRouteID(ctx context.Context) (uint64, error)
- func (s *CatalogStore) NextRouteIDAt(ctx context.Context, ts uint64) (uint64, error)
- func (s *CatalogStore) NextSplitJobID(ctx context.Context) (uint64, error)
- func (s *CatalogStore) NextSplitJobIDAt(ctx context.Context, ts uint64) (uint64, error)
- func (s *CatalogStore) Save(ctx context.Context, expectedVersion uint64, routes []RouteDescriptor) (CatalogSnapshot, error)
- func (s *CatalogStore) SaveSplitJob(ctx context.Context, expected SplitJob, job SplitJob) error
- func (s *CatalogStore) Snapshot(ctx context.Context) (CatalogSnapshot, error)
- func (s *CatalogStore) SnapshotAt(ctx context.Context, ts uint64) (CatalogSnapshot, error)
- func (s *CatalogStore) SplitJob(ctx context.Context, jobID uint64) (SplitJob, bool, error)
- func (s *CatalogStore) SplitJobAt(ctx context.Context, jobID uint64, ts uint64) (SplitJob, bool, error)
- func (s *CatalogStore) Version(ctx context.Context) (uint64, error)
- type CatalogStoreOption
- type CatalogWatchClientProvider
- type CatalogWatcher
- type CatalogWatcherOption
- func WithCatalogWatcherBatchSize(batchSize int) CatalogWatcherOption
- func WithCatalogWatcherInterval(interval time.Duration) CatalogWatcherOption
- func WithCatalogWatcherLogger(logger *slog.Logger) CatalogWatcherOption
- func WithCatalogWatcherSnapshotObserver(observer CatalogSnapshotObserver) CatalogWatcherOption
- type Engine
- func (e *Engine) AppliedCatalogSnapshot() CatalogSnapshot
- func (e *Engine) ApplyDelta(delta CatalogDelta) error
- func (e *Engine) ApplySnapshot(snapshot CatalogSnapshot) error
- func (e *Engine) Current() (RouteHistorySnapshot, bool)
- func (e *Engine) GetIntersectingRoutes(start, end []byte) []Route
- func (e *Engine) GetIntersectingRoutesWithVersion(start, end []byte) ([]Route, uint64)
- func (e *Engine) GetRoute(key []byte) (Route, bool)
- func (e *Engine) GetRouteWithVersion(key []byte) (Route, uint64, bool)
- func (e *Engine) HistoryDepth() int
- func (e *Engine) NextTimestamp() uint64
- func (e *Engine) ResolveRoutesWithVersion(queries ...RouteQuery) ([][]Route, uint64)
- func (e *Engine) SetHistoryDepthForTest(depth int)
- func (e *Engine) SnapshotAt(v uint64) (RouteHistorySnapshot, bool)
- func (e *Engine) Stats() []Route
- func (e *Engine) UpdateRoute(start, end []byte, group uint64)
- func (e *Engine) Version() uint64
- type GRPCCatalogWatcher
- type GRPCCatalogWatcherOption
- type MigrationBracket
- func (b MigrationBracket) ContainsRawKey(rawKey []byte) bool
- func (b MigrationBracket) ContainsRoutedKey(rawKey, routeStart, routeEnd []byte, routeKey func([]byte) []byte) bool
- func (b MigrationBracket) ContainsRoutedVersion(rawKey, value, routeStart, routeEnd []byte, routeKey func([]byte) []byte) bool
- type Route
- type RouteDescriptor
- type RouteHistorySnapshot
- type RouteQuery
- type RouteState
- type SplitJob
- type SplitJobBarrierState
- type SplitJobBracketProgress
- type SplitJobExportPhase
- type SplitJobPhase
Constants ¶
const ( // DefaultCatalogDeltaRetention bounds the durable reconnect window. A // watcher that falls behind this many catalog versions receives a snapshot // reset instead of an incomplete delta sequence. DefaultCatalogDeltaRetention uint64 = 1024 DefaultCatalogDeltaBatchSize = 128 MaxCatalogDeltaBatchSize = 1024 CatalogWatchProtocolVersion uint32 = 1 )
const ( MigrationFamilyUser uint32 = iota + 1 MigrationFamilyTxnIntent MigrationFamilyTxnCommit MigrationFamilyTxnRollback MigrationFamilyTxnSuccess MigrationFamilyTxnMeta MigrationFamilyTxnLock MigrationFamilyListMeta MigrationFamilyListItem MigrationFamilyListMetaDelta MigrationFamilyListClaim MigrationFamilyRedisLegacy MigrationFamilyHash MigrationFamilySet MigrationFamilyZSet MigrationFamilyStreamMeta MigrationFamilyStreamEntry MigrationFamilyDynamoTableMeta MigrationFamilyDynamoTableGeneration MigrationFamilyDynamoItem MigrationFamilyDynamoGSI MigrationFamilySQSQueueMeta MigrationFamilySQSQueueGeneration MigrationFamilySQSQueueSequence MigrationFamilySQSQueueTombstone MigrationFamilySQSMessageData MigrationFamilySQSMessageVisibility MigrationFamilySQSMessageDedup MigrationFamilySQSMessageGroup MigrationFamilySQSMessageByAge MigrationFamilySQSPartitionedMessageData MigrationFamilySQSPartitionedMessageVisibility MigrationFamilySQSPartitionedMessageDedup MigrationFamilySQSPartitionedMessageGroup MigrationFamilySQSPartitionedMessageByAge MigrationFamilyS3BucketMeta MigrationFamilyS3BucketGeneration MigrationFamilyS3ObjectManifest MigrationFamilyS3UploadMeta MigrationFamilyS3UploadPart MigrationFamilyS3Blob MigrationFamilyS3GCUpload MigrationFamilyLegacyListMetaDelta MigrationFamilyS3ChunkRef MigrationFamilyFilesystemChunk MigrationFamilyFilesystemUsage )
const DefaultRouteHistoryDepth = 32
DefaultRouteHistoryDepth is the size of Engine's versioned-snapshot ring used by the Composed-1 M2 plumbing. 32 is conservative against current single-leader catalog churn (operator-frequency, not data-plane) per the design doc §9 Q2; raise if a future control plane generates more than ~tens of versions per second.
Variables ¶
var ( ErrCatalogStoreRequired = errors.New("catalog store is required") ErrCatalogVersionMismatch = errors.New("catalog version mismatch") ErrCatalogVersionOverflow = errors.New("catalog version overflow") ErrCatalogRouteIDOverflow = errors.New("catalog route id overflow") ErrCatalogRouteIDRequired = errors.New("catalog route id is required") ErrCatalogGroupIDRequired = errors.New("catalog group id is required") ErrCatalogDuplicateRouteID = errors.New("catalog route id must be unique") ErrCatalogInvalidRouteRange = errors.New("catalog route range is invalid") ErrCatalogInvalidVersionRecord = errors.New("catalog version record is invalid") ErrCatalogInvalidNextRouteID = errors.New("catalog next route id record is invalid") ErrCatalogInvalidRouteRecord = errors.New("catalog route record is invalid") ErrCatalogInvalidRouteState = errors.New("catalog route state is invalid") ErrCatalogInvalidRouteKey = errors.New("catalog route key is invalid") ErrCatalogRouteKeyIDMismatch = errors.New("catalog route key and record route id mismatch") ErrCatalogRouteV2WriteDisabled = errors.New("catalog route descriptor v2 writes are disabled") )
var ( ErrCatalogInvalidDeltaRecord = errors.New("catalog delta record is invalid") ErrCatalogInvalidDeltaMutation = errors.New("catalog delta mutation is invalid") ErrCatalogDeltaVersionGap = errors.New("catalog delta version is not contiguous") ErrCatalogDeltaBaseMismatch = errors.New("catalog delta base version does not match durable catalog") ErrCatalogDeltaVersionFuture = errors.New("catalog delta cursor is ahead of catalog version") ErrCatalogDeltaLimitInvalid = errors.New("catalog delta limit must be positive") )
var ( ErrEngineSnapshotVersionStale = errors.New("engine snapshot version is stale") ErrEngineSnapshotDuplicateID = errors.New("engine snapshot has duplicate route id") ErrEngineSnapshotRouteOverlap = errors.New("engine snapshot has overlapping routes") ErrEngineSnapshotRouteOrder = errors.New("engine snapshot has invalid route order") ErrEngineDeltaVersionGap = errors.New("engine catalog delta version is not contiguous") )
var ( ErrCatalogWatchClientRequired = errors.New("catalog watch client is required") ErrCatalogWatchEventInvalid = errors.New("catalog watch event is invalid") )
var ( ErrMigrationReservedRange = errors.New("migration range intersects reserved control prefix") ErrMigrationInvalidRoute = errors.New("migration route is invalid") ErrMigrationDataMoveRequired = errors.New("migration data move is not implemented") ErrMigrationSourceRouteChanged = errors.New("migration source route does not match split job") )
var ( ErrCatalogSplitJobIDRequired = errors.New("catalog split job id is required") ErrCatalogSplitJobSourceRouteRequired = errors.New("catalog split job source route id is required") ErrCatalogSplitJobTargetGroupRequired = errors.New("catalog split job target group id is required") ErrCatalogInvalidSplitJobRecord = errors.New("catalog split job record is invalid") ErrCatalogInvalidSplitJobPhase = errors.New("catalog split job phase is invalid") ErrCatalogInvalidSplitJobBarrierState = errors.New("catalog split job barrier state is invalid") ErrCatalogInvalidSplitJobExportPhase = errors.New("catalog split job export phase is invalid") ErrCatalogInvalidSplitJobKey = errors.New("catalog split job key is invalid") ErrCatalogInvalidNextSplitJobID = errors.New("catalog next split job id record is invalid") ErrCatalogSplitJobIDOverflow = errors.New("catalog split job id overflow") ErrCatalogSplitJobKeyIDMismatch = errors.New("catalog split job key and record job id mismatch") ErrCatalogSplitJobConflict = errors.New("catalog split job conflict") ErrCatalogSplitJobTerminalRequired = errors.New("catalog split job terminal state is required") ErrSplitJobOverlap = errors.New("split job overlaps requested route") )
var ErrEngineRequired = errors.New("engine is required")
Functions ¶
func CatalogDeltaFloorKey ¶
func CatalogDeltaFloorKey() []byte
CatalogDeltaFloorKey stores the oldest retained delta version.
func CatalogDeltaKey ¶
CatalogDeltaKey returns the ordered durable key for a catalog delta.
func CatalogDeltaVersionFromKey ¶
CatalogDeltaVersionFromKey parses the version from a durable delta key.
func CatalogNextRouteIDKey ¶
func CatalogNextRouteIDKey() []byte
CatalogNextRouteIDKey returns the reserved key used for next route id storage.
func CatalogNextSplitJobIDKey ¶
func CatalogNextSplitJobIDKey() []byte
CatalogNextSplitJobIDKey returns the reserved key used for split-job ID allocation.
func CatalogRouteIDFromKey ¶
CatalogRouteIDFromKey parses the route ID from a catalog route key.
func CatalogRouteKey ¶
CatalogRouteKey returns the reserved key used for a route descriptor.
func CatalogSplitJobHistoryKey ¶
CatalogSplitJobHistoryKey returns the reserved history key for a terminal split job.
func CatalogSplitJobHistoryKeyParts ¶
CatalogSplitJobHistoryKeyParts parses terminal time and job ID from a history key.
func CatalogSplitJobIDFromKey ¶
CatalogSplitJobIDFromKey parses the job ID from a live split-job key.
func CatalogSplitJobKey ¶
CatalogSplitJobKey returns the reserved live-job key for a split job.
func CatalogVersionKey ¶
func CatalogVersionKey() []byte
CatalogVersionKey returns the reserved key used for catalog version storage.
func DecodeCatalogNextRouteID ¶
DecodeCatalogNextRouteID deserializes a next route id record.
func DecodeCatalogNextSplitJobID ¶
DecodeCatalogNextSplitJobID deserializes a next split-job ID record.
func DecodeCatalogVersion ¶
DecodeCatalogVersion deserializes a catalog version record.
func EncodeCatalogDelta ¶
func EncodeCatalogDelta(delta CatalogDelta) ([]byte, error)
EncodeCatalogDelta serializes a validated catalog transition.
func EncodeCatalogNextRouteID ¶
EncodeCatalogNextRouteID serializes a next route id record.
func EncodeCatalogNextSplitJobID ¶
EncodeCatalogNextSplitJobID serializes a next split-job ID record.
func EncodeCatalogVersion ¶
EncodeCatalogVersion serializes a catalog version record.
func EncodeRouteDescriptor ¶
func EncodeRouteDescriptor(route RouteDescriptor) ([]byte, error)
EncodeRouteDescriptor serializes a route descriptor record.
func EncodeRouteDescriptorForCatalogWrite ¶
func EncodeRouteDescriptorForCatalogWrite(route RouteDescriptor, allowV2 bool) ([]byte, error)
func EncodeRouteDescriptorForCatalogWriteWithSplitAtHLCOffset ¶
func EncodeRouteDescriptorForCatalogWriteWithSplitAtHLCOffset(route RouteDescriptor, allowV2 bool) ([]byte, uint64, error)
EncodeRouteDescriptorForCatalogWriteWithSplitAtHLCOffset serializes a route descriptor and returns the byte offset of its SplitAtHLC field.
func EncodeSplitJob ¶
EncodeSplitJob serializes a SplitJob record as version byte + protobuf body.
func IsCatalogDeltaKey ¶
IsCatalogDeltaKey reports whether key belongs to the delta log keyspace.
func IsCatalogRouteKey ¶
IsCatalogRouteKey reports whether key belongs to the route catalog keyspace.
func IsCatalogSplitJobHistoryKey ¶
IsCatalogSplitJobHistoryKey reports whether key belongs to the split-job history namespace.
func IsCatalogSplitJobKey ¶
IsCatalogSplitJobKey reports whether key belongs to the live split-job namespace.
func IsMigrationKnownInternalKey ¶
IsMigrationKnownInternalKey reports whether a raw key belongs to a concrete internal family owned by an explicit export bracket, by the txn-lock drain, or by a peer-local store that the migrator must not export at all.
func MigrationKnownInternalPrefixes ¶
func MigrationKnownInternalPrefixes() [][]byte
MigrationKnownInternalPrefixes returns the concrete internal data/control prefixes that the user bracket must exclude. It intentionally does not include broad umbrellas such as !txn|, !ddb|, !sqs|, !s3|, or !stream|.
func NextRouteIDFloor ¶
func NextRouteIDFloor(routes []RouteDescriptor) (uint64, error)
NextRouteIDFloor returns the minimum valid next route ID for routes. It is shared by catalog persistence and split planning to keep route-ID allocation rules consistent.
func NextSplitJobIDFloor ¶
NextSplitJobIDFloor returns the minimum valid next split-job ID for jobs.
func RunCatalogWatcher ¶
func RunCatalogWatcher(ctx context.Context, catalog *CatalogStore, engine *Engine, logger *slog.Logger, opts ...CatalogWatcherOption) error
RunCatalogWatcher runs CatalogWatcher with optional logger override.
func ValidateMigrationRouteRange ¶
ValidateMigrationRouteRange rejects route intervals that intersect reserved distribution/migration control namespaces.
Types ¶
type CatalogChangeSet ¶
type CatalogChangeSet struct {
Reset *CatalogSnapshot
Deltas []CatalogDelta
}
CatalogChangeSet contains either a snapshot reset or a contiguous delta batch. Reset is non-nil only when the requested cursor predates retention.
type CatalogDelta ¶
type CatalogDelta struct {
PreviousVersion uint64
Version uint64
Mutations []CatalogRouteMutation
}
CatalogDelta is the durable transition from PreviousVersion to Version.
func DecodeCatalogDelta ¶
func DecodeCatalogDelta(raw []byte) (CatalogDelta, error)
DecodeCatalogDelta deserializes and validates a catalog transition.
type CatalogMigrationStoreResolver ¶
CatalogMigrationStoreResolver resolves the local MVCC store for a data group.
type CatalogMutationOp ¶
type CatalogMutationOp byte
CatalogMutationOp describes one route-level catalog change.
const ( CatalogMutationUpsert CatalogMutationOp = 1 CatalogMutationDelete CatalogMutationOp = 2 )
type CatalogRouteMutation ¶
type CatalogRouteMutation struct {
Op CatalogMutationOp
RouteID uint64
Route RouteDescriptor
}
CatalogRouteMutation changes one durable route descriptor.
type CatalogSnapshot ¶
type CatalogSnapshot struct {
Version uint64
Routes []RouteDescriptor
ReadTS uint64
}
CatalogSnapshot is a point-in-time snapshot of the route catalog.
func EnsureCatalogSnapshot ¶
func EnsureCatalogSnapshot(ctx context.Context, catalog *CatalogStore, engine *Engine) (CatalogSnapshot, error)
EnsureCatalogSnapshot makes engine and durable catalog consistent at startup.
If the durable catalog is empty (version 0, no routes), the current in-memory engine routes are persisted as the initial catalog snapshot with generated non-zero RouteIDs. Then the resolved snapshot is applied back to engine.
type CatalogSnapshotObserver ¶
type CatalogSnapshotObserver func(CatalogSnapshot)
CatalogSnapshotObserver receives each snapshot successfully applied by the watcher. Implementations run synchronously on the watcher goroutine and must not block.
type CatalogStore ¶
type CatalogStore struct {
// contains filtered or unexported fields
}
CatalogStore provides persistence helpers for route catalog state.
func NewCatalogStore ¶
func NewCatalogStore(st store.MVCCStore, opts ...CatalogStoreOption) *CatalogStore
NewCatalogStore creates a route catalog persistence helper.
func (*CatalogStore) AllowsRouteDescriptorV2Writes ¶
func (s *CatalogStore) AllowsRouteDescriptorV2Writes() bool
func (*CatalogStore) BuildDeltaMutationsAt ¶
func (s *CatalogStore) BuildDeltaMutationsAt(ctx context.Context, readTS uint64, delta CatalogDelta) ([]*store.KVPairMutation, error)
BuildDeltaMutationsAt returns the durable delta/floor/retention mutations that must be committed atomically with the catalog version transition.
func (*CatalogStore) ChangesSince ¶
func (s *CatalogStore) ChangesSince(ctx context.Context, afterVersion uint64, limit int) (CatalogChangeSet, error)
ChangesSince reads a consistent reconnect batch after afterVersion.
func (*CatalogStore) CreateSplitJob ¶
func (s *CatalogStore) CreateSplitJob(ctx context.Context, job SplitJob) error
CreateSplitJob creates a live split job and advances next_job_id when needed.
func (*CatalogStore) DeleteSplitJob ¶
func (s *CatalogStore) DeleteSplitJob(ctx context.Context, jobID uint64) error
DeleteSplitJob deletes a live split job.
func (*CatalogStore) DeltaFloor ¶
func (s *CatalogStore) DeltaFloor(ctx context.Context) (uint64, error)
DeltaFloor returns the oldest retained durable delta version. Zero means the catalog predates delta logging and a watcher must request a snapshot reset.
func (*CatalogStore) LatestCommitTS ¶
func (s *CatalogStore) LatestCommitTS() uint64
LatestCommitTS returns the local catalog store watermark without reading catalog data. Callers use it as the pre-Phase-D legacy timestamp input before selecting the transaction snapshot through the dedicated TSO.
func (*CatalogStore) ListSplitJobs ¶
func (s *CatalogStore) ListSplitJobs(ctx context.Context) ([]SplitJob, error)
ListSplitJobs returns live and history split jobs at the latest timestamp.
func (*CatalogStore) ListSplitJobsAt ¶
ListSplitJobsAt returns live and history split jobs at a snapshot timestamp.
func (*CatalogStore) MoveSplitJobToHistory ¶
func (s *CatalogStore) MoveSplitJobToHistory(ctx context.Context, expected SplitJob, job SplitJob) error
MoveSplitJobToHistory moves a terminal split job from live state to history.
func (*CatalogStore) NextRouteID ¶
func (s *CatalogStore) NextRouteID(ctx context.Context) (uint64, error)
NextRouteID reads the next route id counter from catalog metadata.
func (*CatalogStore) NextRouteIDAt ¶
NextRouteIDAt reads the next route id counter at a given snapshot timestamp.
func (*CatalogStore) NextSplitJobID ¶
func (s *CatalogStore) NextSplitJobID(ctx context.Context) (uint64, error)
NextSplitJobID reads the next split-job ID counter from catalog metadata.
func (*CatalogStore) NextSplitJobIDAt ¶
NextSplitJobIDAt reads the next split-job ID counter at a given snapshot timestamp.
func (*CatalogStore) Save ¶
func (s *CatalogStore) Save(ctx context.Context, expectedVersion uint64, routes []RouteDescriptor) (CatalogSnapshot, error)
Save updates the route catalog using optimistic version checks and bumps the catalog version by exactly one on success.
func (*CatalogStore) SaveSplitJob ¶
SaveSplitJob updates a live split job if it still matches expected.
func (*CatalogStore) Snapshot ¶
func (s *CatalogStore) Snapshot(ctx context.Context) (CatalogSnapshot, error)
Snapshot reads a consistent route catalog snapshot at the store's latest known commit timestamp.
func (*CatalogStore) SnapshotAt ¶
func (s *CatalogStore) SnapshotAt(ctx context.Context, ts uint64) (CatalogSnapshot, error)
SnapshotAt reads a consistent route catalog snapshot at a specific MVCC timestamp.
func (*CatalogStore) SplitJob ¶
SplitJob reads a live or history split job by ID at the latest timestamp.
func (*CatalogStore) SplitJobAt ¶
func (s *CatalogStore) SplitJobAt(ctx context.Context, jobID uint64, ts uint64) (SplitJob, bool, error)
SplitJobAt reads a live or history split job by ID at a snapshot timestamp.
type CatalogStoreOption ¶
type CatalogStoreOption func(*CatalogStore)
func WithCatalogMigrationStoreResolver ¶
func WithCatalogMigrationStoreResolver(resolver CatalogMigrationStoreResolver) CatalogStoreOption
WithCatalogMigrationStoreResolver makes split-job finalization retire target-local migration metadata from the target data group store.
func WithCatalogRouteDescriptorV2Writes ¶
func WithCatalogRouteDescriptorV2Writes(enabled bool) CatalogStoreOption
type CatalogWatchClientProvider ¶
type CatalogWatchClientProvider func(context.Context) (pb.DistributionClient, error)
CatalogWatchClientProvider resolves the Distribution endpoint used for one capability negotiation and stream attempt. Production resolves the current default-group leader again after every disconnect.
type CatalogWatcher ¶
type CatalogWatcher struct {
// contains filtered or unexported fields
}
CatalogWatcher periodically refreshes Engine from durable catalog snapshots.
func NewCatalogWatcher ¶
func NewCatalogWatcher(catalog *CatalogStore, engine *Engine, opts ...CatalogWatcherOption) *CatalogWatcher
NewCatalogWatcher creates a watcher that polls the durable route catalog and applies newer snapshots to the in-memory engine.
type CatalogWatcherOption ¶
type CatalogWatcherOption func(*CatalogWatcher)
CatalogWatcherOption customizes CatalogWatcher behavior.
func WithCatalogWatcherBatchSize ¶
func WithCatalogWatcherBatchSize(batchSize int) CatalogWatcherOption
WithCatalogWatcherBatchSize sets the maximum number of deltas applied by one synchronization pass.
func WithCatalogWatcherInterval ¶
func WithCatalogWatcherInterval(interval time.Duration) CatalogWatcherOption
WithCatalogWatcherInterval sets the catalog polling interval.
func WithCatalogWatcherLogger ¶
func WithCatalogWatcherLogger(logger *slog.Logger) CatalogWatcherOption
WithCatalogWatcherLogger sets the logger for watcher background retries.
func WithCatalogWatcherSnapshotObserver ¶
func WithCatalogWatcherSnapshotObserver(observer CatalogSnapshotObserver) CatalogWatcherOption
WithCatalogWatcherSnapshotObserver installs a post-apply snapshot callback.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine holds in-memory metadata of routes and provides timestamp generation.
func NewEngineWithDefaultRoute ¶
func NewEngineWithDefaultRoute() *Engine
NewEngineWithDefaultRoute creates an Engine and registers a default route covering the full keyspace with a default group ID. The default route is also recorded in the M2 history ring as the version-0 snapshot so transactions that observed catalogVersion = 0 can resolve their read-set owner through SnapshotAt(0).
func (*Engine) AppliedCatalogSnapshot ¶
func (e *Engine) AppliedCatalogSnapshot() CatalogSnapshot
AppliedCatalogSnapshot returns the routes the engine is currently serving, paired with the catalog version they were applied at. It is the engine's own view rather than the persisted catalog's, which is what a caller mid-catch-up needs: the store may already be several delta batches ahead.
ReadTS is left zero because these routes come from applied deltas, not from a point-in-time catalog read.
func (*Engine) ApplyDelta ¶
func (e *Engine) ApplyDelta(delta CatalogDelta) error
ApplyDelta atomically publishes one contiguous catalog transition. Readers observe either the complete previous route table or the complete next table.
func (*Engine) ApplySnapshot ¶
func (e *Engine) ApplySnapshot(snapshot CatalogSnapshot) error
ApplySnapshot atomically replaces all in-memory routes with the provided catalog snapshot when the snapshot version is newer.
func (*Engine) Current ¶
func (e *Engine) Current() (RouteHistorySnapshot, bool)
Current returns the route catalog snapshot at the engine's current catalogVersion. Returns (zero, false) when the history ring has not been initialised (bare-struct Engine). Used by the M3 Composed-1 cross-version-read fence (design doc §4.4) — the gate compares the txn's observed-version owner against the current owner so a route shift between BeginTxn and Commit is caught before it can produce a G1c anomaly across a cross-group MoveRange / SplitRange.
func (*Engine) GetIntersectingRoutes ¶
GetIntersectingRoutes returns all routes whose key ranges intersect with [start, end). A route [rStart, rEnd) intersects with [start, end) if: - rStart < end (or end is nil, meaning unbounded scan) - start < rEnd (or rEnd is nil, meaning unbounded route)
func (*Engine) GetIntersectingRoutesWithVersion ¶
GetIntersectingRoutesWithVersion returns intersecting routes and the catalog version from the same locked snapshot.
func (*Engine) GetRouteWithVersion ¶
GetRouteWithVersion finds a route and returns the catalog version from the same locked snapshot. Callers can use the version as a read-routing fence.
func (*Engine) HistoryDepth ¶
HistoryDepth returns the configured ring depth for diagnostics.
func (*Engine) NextTimestamp ¶
NextTimestamp returns a monotonic increasing timestamp.
func (*Engine) ResolveRoutesWithVersion ¶
func (e *Engine) ResolveRoutesWithVersion(queries ...RouteQuery) ([][]Route, uint64)
ResolveRoutesWithVersion answers every query from a single locked catalog snapshot and returns the one version that produced all of them. Callers that need more than one route candidate must use this instead of repeating GetRouteWithVersion / GetIntersectingRoutesWithVersion: separate calls can straddle a catalog update and pair a stale route with a newer version, which turns that version into a fence the route actually read was never checked against.
func (*Engine) SetHistoryDepthForTest ¶
SetHistoryDepthForTest overrides the FIFO ring depth from outside the package. Test-only. Callers should set the depth before sharing the Engine with concurrent SnapshotAt/Current readers to avoid interleaving surprises around the eviction watermark, but the write itself is lock-protected (e.mu.Lock below) so it is safe to call from any goroutine that does not also expect a consistent SnapshotAt view across the depth change.
Exists so tests in the kv package can drive eviction-trigger scenarios without adding a constructor option just for tests (claude review on PR #894). Production code must use DefaultRouteHistoryDepth (32) or a future operator-exposed config knob.
Fails fast on depth <= 0 (coderabbit minor on PR #895): recordHistorySnapshotLocked's eviction path indexes historyOrder[0], so a zero/negative depth would surface as a confusing index-out-of-range deep in the apply path instead of at the misconfigured test seam. When shrinking depth below the current ring size, evict the excess oldest entries immediately rather than letting the next record see len(historyOrder) > historyDepth (gemini medium on PR #895 — without this trim, the next recordHistorySnapshotLocked's `make([]uint64, len-1, historyDepth)` would panic on len-1 > historyDepth).
func (*Engine) SnapshotAt ¶
func (e *Engine) SnapshotAt(v uint64) (RouteHistorySnapshot, bool)
SnapshotAt returns the route catalog snapshot recorded at version v. Returns (zero, false) when v is not in the ring — either because v is in the future (> catalogVersion), or because the FIFO ring has evicted v (it was older than the historyDepth-most-recent versions). The M3 Composed-1 gate (design doc §4.3) treats the not-found case as a hard error and triggers a coordinator retry, so retention depth is a liveness knob, not a safety knob.
func (*Engine) UpdateRoute ¶
UpdateRoute registers or updates a route for the given key range. Routes are stored sorted by Start.
type GRPCCatalogWatcher ¶
type GRPCCatalogWatcher struct {
// contains filtered or unexported fields
}
GRPCCatalogWatcher mirrors a remote Distribution catalog into Engine.
func NewGRPCCatalogWatcher ¶
func NewGRPCCatalogWatcher(client pb.DistributionClient, engine *Engine, opts ...GRPCCatalogWatcherOption) *GRPCCatalogWatcher
NewGRPCCatalogWatcher creates a capability-negotiated remote mirror.
func NewResolvingGRPCCatalogWatcher ¶
func NewResolvingGRPCCatalogWatcher( provider CatalogWatchClientProvider, engine *Engine, opts ...GRPCCatalogWatcherOption, ) *GRPCCatalogWatcher
NewResolvingGRPCCatalogWatcher creates a mirror that re-resolves its remote endpoint before every reconnect attempt.
type GRPCCatalogWatcherOption ¶
type GRPCCatalogWatcherOption func(*GRPCCatalogWatcher)
GRPCCatalogWatcherOption customizes a remote catalog mirror.
func WithGRPCCatalogWatcherLogger ¶
func WithGRPCCatalogWatcherLogger(logger *slog.Logger) GRPCCatalogWatcherOption
WithGRPCCatalogWatcherLogger sets the reconnect logger.
func WithGRPCCatalogWatcherRetryInterval ¶
func WithGRPCCatalogWatcherRetryInterval(interval time.Duration) GRPCCatalogWatcherOption
WithGRPCCatalogWatcherRetryInterval sets reconnect and legacy polling delay.
type MigrationBracket ¶
type MigrationBracket struct {
BracketID uint64
Family uint32
Start []byte
End []byte
ExcludePrefixes [][]byte
ExcludeKnownInternal bool
DrainOnly bool
RequiresRouteKeyCheck bool
RequiresDecodedS3 bool
}
MigrationBracket is a raw MVCC export or drain slice used by the migrator.
func PlanExportBrackets ¶
func PlanExportBrackets(routeStart, routeEnd []byte) ([]MigrationBracket, error)
PlanExportBrackets returns the data-copy bracket plan. Intent locks are deliberately absent because the source drains them route-faithfully before cutover and the target must not materialize in-flight intents as data.
func PlanMigrationBrackets ¶
func PlanMigrationBrackets(routeStart, routeEnd []byte) ([]MigrationBracket, error)
PlanMigrationBrackets returns the full M2 migration plan, including the drain-only transaction lock bracket. Data export callers should use PlanExportBrackets, which omits drain-only control state.
func (MigrationBracket) ContainsRawKey ¶
func (b MigrationBracket) ContainsRawKey(rawKey []byte) bool
ContainsRawKey reports whether rawKey is inside the bracket's raw scan interval after applying bracket-local exclusions. Route ownership still requires the caller's RouteKeyFilter for every bracket.
func (MigrationBracket) ContainsRoutedKey ¶
func (b MigrationBracket) ContainsRoutedKey(rawKey, routeStart, routeEnd []byte, routeKey func([]byte) []byte) bool
ContainsRoutedKey applies both the bracket's raw family interval and its route ownership predicate. S3 bucket-level auxiliary rows do not encode an object route key, so they are matched by bucket route-prefix intersection.
func (MigrationBracket) ContainsRoutedVersion ¶
func (b MigrationBracket) ContainsRoutedVersion(rawKey, value, routeStart, routeEnd []byte, routeKey func([]byte) []byte) bool
ContainsRoutedVersion is the value-aware variant of ContainsRoutedKey. It is needed for legacy list metadata because old delta keys overlap byte-for-byte with base metadata keys whose user key begins with "d|".
type Route ¶
type Route struct {
// RouteID is the durable identifier assigned by route catalog.
// Zero means ephemeral/non-catalog routes.
RouteID uint64
// Start marks the inclusive beginning of the range.
Start []byte
// End marks the exclusive end of the range. nil means unbounded.
End []byte
// GroupID identifies the raft group for the range starting at Start.
GroupID uint64
// State tracks control-plane state for this route.
State RouteState
// StagedVisibilityActive allows serving reads to merge staged migration rows.
StagedVisibilityActive bool
// MigrationJobID identifies the active staged migration job.
MigrationJobID uint64
// MinWriteTSExclusive rejects writes at or below the migration cutover floor.
MinWriteTSExclusive uint64
// Load tracks the number of accesses served by this range.
Load uint64
}
Route represents a mapping from a key range to a raft group. Ranges are right half-open intervals: [Start, End). Start is inclusive and End is exclusive. A nil End denotes an unbounded interval extending to positive infinity.
func RoutesFromCatalogSnapshot ¶
func RoutesFromCatalogSnapshot(snapshot CatalogSnapshot) ([]Route, error)
RoutesFromCatalogSnapshot validates and materializes the immutable route view contained in a durable catalog snapshot. Callers that need ownership as of an MVCC timestamp must use this view instead of the live Engine.
type RouteDescriptor ¶
type RouteDescriptor struct {
RouteID uint64
Start []byte
End []byte
GroupID uint64
State RouteState
ParentRouteID uint64
StagedVisibilityActive bool
MigrationJobID uint64
MinWriteTSExclusive uint64
SplitAtHLC uint64
}
RouteDescriptor is the durable representation of a route.
func CloneRouteDescriptor ¶
func CloneRouteDescriptor(route RouteDescriptor) RouteDescriptor
CloneRouteDescriptor returns a deep copy of route.
func DecodeRouteDescriptor ¶
func DecodeRouteDescriptor(raw []byte) (RouteDescriptor, error)
DecodeRouteDescriptor deserializes a route descriptor record.
type RouteHistorySnapshot ¶
type RouteHistorySnapshot struct {
// contains filtered or unexported fields
}
RouteHistorySnapshot is a point-in-time view of the route catalog at a specific version. Returned by Engine.SnapshotAt for the M3 Composed-1 commit-time gate. Carries an immutable copy of the catalog's routes at the recorded version so a caller can resolve ownership without holding the Engine lock.
func (RouteHistorySnapshot) IntersectingRoutes ¶
func (s RouteHistorySnapshot) IntersectingRoutes(start, end []byte) []Route
IntersectingRoutes returns every route whose range intersects [start, end) in this snapshot. A nil end denotes +infinity.
func (RouteHistorySnapshot) OwnerOf ¶
func (s RouteHistorySnapshot) OwnerOf(key []byte) (uint64, bool)
OwnerOf returns the Raft group ID that owned key at this snapshot's version. Returns (0, false) when no route covers key (the pre-bootstrap state or an explicitly-uncovered range). Mirrors Engine.GetRoute's right-half-open interval semantics but against the historical snapshot, not the live engine state.
Routes are sorted by Start (recordHistorySnapshotLocked clones from e.routes, which Engine.UpdateRoute / routesFromCatalog keep sorted), so the scan can break the moment key < r.Start — every later route has a strictly greater Start and cannot cover key either. This matters because M3 puts OwnerOf on every txn commit's apply path (claude review on PR #894 — break-vs-continue lifts the worst-case scan from O(N) to "first non-covering gap" without changing the resolution semantics).
func (RouteHistorySnapshot) RouteOf ¶
func (s RouteHistorySnapshot) RouteOf(key []byte) (Route, bool)
RouteOf returns the route that covered key at this snapshot's version.
func (RouteHistorySnapshot) Version ¶
func (s RouteHistorySnapshot) Version() uint64
Version returns the catalog version this snapshot was recorded at.
type RouteQuery ¶
RouteQuery is one lookup for ResolveRoutesWithVersion. Exact resolves the single route containing Start; otherwise every route intersecting [Start, End) is returned.
type RouteState ¶
type RouteState byte
RouteState describes the control-plane state of a route.
const ( // RouteStateActive is a normal serving route. RouteStateActive RouteState = iota // RouteStateWriteFenced blocks writes during cutover. RouteStateWriteFenced // RouteStateMigratingSource means range data is being copied out. RouteStateMigratingSource // RouteStateMigratingTarget means range data is being copied in. RouteStateMigratingTarget )
type SplitJob ¶
type SplitJob struct {
JobID uint64
SourceRouteID uint64
SplitKey []byte
TargetGroupID uint64
Phase SplitJobPhase
RetryPhase SplitJobPhase
AbandonFromPhase SplitJobPhase
SnapshotTS uint64
SnapshotMinAdmittedTS uint64
WriteTrackerArmed bool
DeltaFloor uint64
PostFenceDrainCompleted bool
FenceTS uint64
CutoverVersion uint64
CutoverReadFenceState SplitJobBarrierState
TargetStagedReadinessState SplitJobBarrierState
SourceCutoverReadFenceAckCursor []byte
TargetStagedReadinessAckCursor []byte
Cursor []byte
MaxImportedTS uint64
TargetPromotionDone bool
PromotionCompletedTS uint64
FenceCatalogVersion uint64
FenceAckCursor []byte
SourceCutoverAckCursor []byte
SourceReadDrainCursor []byte
TargetClearedDescriptorAckCursor []byte
BracketProgress []SplitJobBracketProgress
SourceRetentionPinTS uint64
LastError string
StartedAtMs int64
UpdatedAtMs int64
TerminalAtMs int64
}
SplitJob is the durable default-group state for a range split migration.
func AdvanceSameGroupNoop ¶
func AdvanceSameGroupNoop(job SplitJob, source RouteDescriptor, nowMs int64) (SplitJob, error)
AdvanceSameGroupNoop completes the PR4 same-group path without attempting data movement. Cross-group data copy is added by later M2 PRs.
func CloneSplitJob ¶
func DecodeSplitJob ¶
DecodeSplitJob deserializes a SplitJob record.
func InitializeSplitJobPlan ¶
func InitializeSplitJobPlan(job SplitJob, source RouteDescriptor, nowMs int64) (SplitJob, error)
InitializeSplitJobPlan validates the source route and seeds the job's bracket progress for the moving right child [SplitKey, source.End).
type SplitJobBarrierState ¶
type SplitJobBarrierState byte
SplitJobBarrierState is a restart witness for per-voter barrier progress.
const ( SplitJobBarrierNone SplitJobBarrierState = iota SplitJobBarrierArming SplitJobBarrierArmed SplitJobBarrierClearing )
type SplitJobBracketProgress ¶
type SplitJobBracketProgress struct {
BracketID uint64
Family uint32
ExportPhase SplitJobExportPhase
Cursor []byte
Done bool
ScannedBytes uint64
AcceptedRows uint64
LastAckedBatchSeq uint64
}
SplitJobBracketProgress is per-family export-bracket resume state.
func SplitJobBracketProgressForPlan ¶
func SplitJobBracketProgressForPlan(brackets []MigrationBracket, phase SplitJobExportPhase) []SplitJobBracketProgress
SplitJobBracketProgressForPlan creates durable per-bracket resume state for a SplitJob phase.
type SplitJobExportPhase ¶
type SplitJobExportPhase byte
SplitJobExportPhase records which export window a bracket is scanning.
const ( SplitJobExportPhaseNone SplitJobExportPhase = iota SplitJobExportPhaseBackfill SplitJobExportPhaseDeltaCopy )
type SplitJobPhase ¶
type SplitJobPhase byte
SplitJobPhase is the durable phase of a split migration job.
const ( SplitJobPhaseNone SplitJobPhase = iota SplitJobPhasePlanned SplitJobPhaseBackfill SplitJobPhaseFence SplitJobPhaseDeltaCopy SplitJobPhaseCutover SplitJobPhaseCleanup SplitJobPhaseDone SplitJobPhaseFailed SplitJobPhaseAbandoning SplitJobPhaseAbandoned )