Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrConcurrentModification = errors.New("manifest concurrently modified")
ErrConcurrentModification indicates manifest was modified by another process.
var ErrManifestMetadataContractViolation = errors.New("manifest metadata contract violated")
ErrManifestMetadataContractViolation indicates provider.SaveManifest succeeded but did not advance manifest metadata as required by FileProvider contract.
var ErrSourceChecksumMismatch = errors.New("compaction source checksum mismatch")
ErrSourceChecksumMismatch marks a rewrite input whose bytes no longer hash to its manifest stamp. The rewrite must NOT proceed: runRewrite merges the sources into the new base and then deletes them, so this gate is the last moment silent corruption (#347) is both detectable and still attributable to a named object. Probe failures never map to this error — a failed GET is transient infrastructure, not a corruption verdict.
Functions ¶
func IsConcurrentModification ¶ added in v0.2.0
IsConcurrentModification reports whether err is a confirmed HTTP 412 conditional-put rejection — the only save failure that proves the write did not commit. Exported for callers outside this package (the manifest-reconcile tool) that save manifests under an etag without going through the compactor's saveManifestChecked.
Types ¶
type CompactionOutcome ¶ added in v0.1.0
type CompactionOutcome string
CompactionOutcome describes the result of a compaction pass for a single schema.
const ( Noop CompactionOutcome = "noop" PromotionApplied CompactionOutcome = "promotion_applied" // RewritePending is reported when the dirty ratio calls for a rewrite but // no Merger is wired, so the pass leaves everything untouched. RewritePending CompactionOutcome = "rewrite_pending" // RewriteApplied is reported when the dirty-ratio rewrite merged the full // base+delta set into a new base file and committed the manifest swap. RewriteApplied CompactionOutcome = "rewrite_applied" )
type CompactionResult ¶ added in v0.1.0
type CompactionResult struct {
Outcome CompactionOutcome
SchemaID int16
Version int64
DirtyRatio float64
BaseMB int64
DeltaMB int64
// Rewrite metadata, populated only when Outcome is RewriteApplied.
FilesMerged int // source files folded into the new base
RowsIn int64 // rows read across all source files
RowsOut int64 // surviving LWW winners written to the new base
NewBaseKey string // S3 key of the merged base parquet
}
CompactionResult carries the outcome and metadata from a compaction pass.
type Compactor ¶
type Compactor struct {
Logger *zap.Logger
Config cdc.CompactionConfig
Provider FileProvider
Merger Merger
S3 cdc.S3ObjectClient
Bucket string
DataPrefix string // root prefix for parquet files
Resolver manifest.PathResolver
// ObjectReader hashes published objects for manifest checksum stamping
// and pre-merge input verification (#347). Nil disables both.
ObjectReader cdc.S3GetClient
}
Compactor performs Base/Delta maintenance per schema. The dirty-ratio rewrite (#188) additionally needs Merger, S3, Bucket and DataPrefix; when any is missing a rewrite-eligible pass reports RewritePending instead.
type DuckMerger ¶ added in v0.2.0
type DuckMerger struct {
DB *sql.DB
// CopyOptions overrides the parquet COPY options (defaults to the CDC
// exporters' FORMAT PARQUET, V2, ZSTD level 3).
CopyOptions string
// Logger reports the best-effort manifest stamp probe (#256). Optional —
// nil is safe and silences it.
Logger *zap.Logger
// contains filtered or unexported fields
}
DuckMerger implements Merger over a DuckDB connection that already has httpfs and S3 credentials configured — cdc.NewDuckExporter's DB is the production source of exactly that.
func (*DuckMerger) MergeToTmp ¶ added in v0.2.0
func (d *DuckMerger) MergeToTmp(ctx context.Context, sourceURIs []string, tmpURI string) (MergeStats, error)
type FileProvider ¶
type FileProvider interface {
LoadManifest(ctx context.Context, schemaID int16) (*manifest.Manifest, string, error)
// SaveManifest persists the manifest as a commit point.
// Implementations must mutate the provided manifest pointer in-place on
// successful save:
// - Version must increase monotonically.
// - UpdatedAtMs must move forward.
// Compactor relies on the same pointer carrying updated metadata and does
// not mutate those fields directly.
SaveManifest(ctx context.Context, schemaID int16, m *manifest.Manifest, etag string) (string, error)
}
FileProvider fetches manifest and lists actual files (optionally cross-check).
type ManifestProvider ¶
type ManifestProvider struct {
Store manifest.Store
Resolver manifest.PathResolver
}
ManifestProvider adapts manifest.Store + resolver to FileProvider.
func NewFSManifestProvider ¶
func NewFSManifestProvider(cfg cdc.ManifestConfig, rootFS fs.FS) *ManifestProvider
NewFSManifestProvider creates a ManifestProvider backed by local filesystem. Useful for testing and local development.
func NewManifestProvider ¶
func NewManifestProvider(cfg cdc.ManifestConfig, store manifest.Store) *ManifestProvider
NewManifestProvider creates a ManifestProvider from a ManifestConfig and Store. Use this to wire up the provider from configuration.
func NewS3ManifestProvider ¶
func NewS3ManifestProvider(cfg cdc.ManifestConfig, s3Client manifest.S3Client) *ManifestProvider
NewS3ManifestProvider creates a ManifestProvider backed by S3. It accepts any manifest.S3Client (Get/Put) so tests can decorate the real client.
func (*ManifestProvider) LoadManifest ¶
type MergeStats ¶ added in v0.2.0
type MergeStats struct {
RowsIn int64 // version rows read across all source files
RowsOut int64 // surviving LWW winners written to the merged file
RowIDMin string // "" when the merge produced zero rows
RowIDMax string
CreatedMin int64
CreatedMax int64
// Columns is the merged file's footer schema (name → DuckDB type),
// stamped into the manifest entry (#256). Nil when the self-describe
// failed; the entry then stays unstamped and reads fall back to probing.
Columns map[string]string
}
MergeStats carries what the rewrite orchestration needs to build the new base FileEntry and the CompactionResult counters.
func SingleFileStats ¶ added in v0.2.0
SingleFileStats recomputes one parquet file's manifest metadata (row count, row_id min/max, changed_at min/max) from its contents via the given DuckDB session. It runs the same stats query the merge path uses for a freshly merged file, so a manifest entry rebuilt from it matches what compaction itself would have written. The manifest-reconcile tool uses this to repair orphaned delta files (#203) without trusting filenames.
type Merger ¶ added in v0.2.0
type Merger interface {
MergeToTmp(ctx context.Context, sourceURIs []string, tmpURI string) (MergeStats, error)
}
Merger folds a schema's complete base+delta parquet set into one merged base file at tmpURI. Implementations only stage the tmp object; the compactor owns promotion to the final key, the manifest swap, and source cleanup.
type UncoveredRow ¶ added in v0.2.0
UncoveredRow is one row_id in an orphan parquet whose newest uncovered version is not superseded by any manifest-listed file. Tombstone reports whether that version is a delete marker — re-appending an uncovered tombstone RESTORES a lost delete, while re-appending an uncovered live version of a Postgres-deleted row resurrects it.
func UncoveredRows ¶ added in v0.2.0
func UncoveredRows(ctx context.Context, db *sql.DB, orphanURI string, listedURIs []string) ([]UncoveredRow, error)
UncoveredRows returns, per row_id, the orphan parquet's versions that no listed file supersedes. Coverage is version-aware: a listed version with changed_at >= the orphan version's covers it (the anti-join is >=, so an equal-changed_at listed version counts as covering — post-#274 equal ties are value-identical copies with an unspecified winner), so a same-row lost update — an orphan carrying a NEWER version than anything listed — still counts as uncovered. The manifest-reconcile tool (#203) builds its repair verdict on this: a row_id-only anti-join would misclassify lost updates as deletable leftovers.