migrate

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package migrate — this file is the orchestration capstone (MIGR-01/ MIGR-02): Run wires the read-only reader (reader.go/translate.go), the resumable progress cursor (progress.go), the D-09 invariant pass (validate.go), and the atomic directory swap (swap.go) into one call that converts a TS CodeGraph SQLite index into a healthy new-format store.

Sequence (07-RESEARCH.md §System Architecture Diagram): detect + guard the source -> open/create a deterministic sibling partial store -> resume from the durable cursor if present -> stream files, then nodes, then edges (nodes-before-edges so PutEdge's ownerPath resolves, D-04) in bounded, durably-checkpointed batches -> recompute per-file edge_count from the written x/ index (Pitfall 7) -> run validate (D-09) -> stamp Meta.healthy only after validate passes (D-10) -> atomically swap the partial store into place (D-07). Every I/O error is wrapped and returned — never swallowed (this is the highest silent-failure-risk plan in the phase).

Package migrate — this file is the durable, resumable migration cursor (D-06). A Progress record is persisted through the Wave-1 (07-02) graphstore.Writer.PutMigration/Reader.GetMigration pair under the target store's own m/migration meta key, so an interrupted migration can be resumed from the last-committed table+rowid rather than restarted from scratch.

Package migrate implements the one-way TS CodeGraph SQLite → codegraph-go Pebble migration (MIGR-01/MIGR-02). This file is the read half: it opens the source TS `.codegraph/*.db` read-only, detects a genuine TS source, guards the observed schema version, and streams rows from the allow-listed files/nodes/edges tables with defensive column enumeration (07-RESEARCH.md Pattern 1) and mandatory rows.Err() checks (07-RESEARCH.md Pitfall 2 — mirrors internal/graphstore/export.go's exportNamespace "return iter.Error() after the loop" idiom).

Package migrate — this file is the D-09 post-migration invariant pass: count reconciliation (de-dup aware for edges) plus referential-integrity scanning (zero-dangling-edges, file:-endpoint exempt), driving the fail-loud-vs-`--drop-dangling` policy that gates Meta.healthy (D-10). validate reads the migrated store back through the existing graphstore.Reader surface — no new read machinery, per 07-PATTERNS.md.

Index

Constants

View Source
const (
	StatusInProgress = "in_progress"
	StatusComplete   = "complete"
)

Status values for Progress.Status.

Variables

View Source
var ErrNotATSSource = errors.New("migrate: not a TS CodeGraph source (missing schema_versions/nodes/edges)")

ErrNotATSSource is returned by DetectTS when the opened SQLite file is missing one or more of the required TS tables (schema_versions, nodes, edges) — i.e. it is not a genuine TS CodeGraph index.

View Source
var ErrUnsupportedSchemaVersion = errors.New("migrate: unsupported source schema version")

ErrUnsupportedSchemaVersion is returned by SchemaVersion when the source's max(schema_versions.version) falls outside [minSupportedSchemaVersion, maxSupportedSchemaVersion].

Functions

func FindDBFile

func FindDBFile(codegraphDir string) (string, error)

FindDBFile autodetects the single *.db file inside a TS .codegraph/ directory. Returns an error if zero or more than one is found.

Types

type DanglingEdge

type DanglingEdge struct {
	Source, Kind, Target string

	// MissingSource / MissingTarget record which endpoint(s) failed to
	// resolve; either or both may be true.
	MissingSource, MissingTarget bool
}

DanglingEdge identifies a migrated edge whose source and/or target endpoint failed to resolve to a migrated node (file:-prefixed endpoints are exempt — see isFileEndpoint).

type Options

type Options struct {
	// Force allows overwriting a non-empty target that isn't recognizably a
	// prior migration (D-08). Consumed by the orchestration layer (07-06);
	// validate itself does not read it.
	Force bool

	// DropDangling, when true, makes scanDangling delete each dangling
	// (non-file:) edge and record it in Report.Dropped instead of failing
	// loud — an explicit, opt-in lossy migration (D-09.2).
	DropDangling bool
}

Options controls behavior shared across internal/migrate's orchestration (07-06) and validation phases. This is the package's single definition — 07-06's migrate.go reconciles with it rather than redeclaring it.

type Progress

type Progress struct {
	SourceSchemaVersion int    `json:"source_schema_version"`
	TargetSchemaVersion uint32 `json:"target_schema_version"`
	LastTable           string `json:"last_table"`
	LastRowID           int64  `json:"last_row_id"`
	Status              string `json:"status"`

	// Reconciled source row counts, persisted when the cursor is stamped
	// StatusComplete (WR-01). finishFromComplete reads these back into the
	// resumed/recovered Result.Report so the CLI's "migrated/source"
	// reconciliation line shows the real source denominators instead of 0 —
	// on an in-place recovery the source is gone and cannot be re-counted, so
	// it must have been persisted at completion. Zero on in_progress cursors.
	SourceNodeCount int64 `json:"source_node_count,omitempty"`
	SourceEdgeCount int64 `json:"source_edge_count,omitempty"`
	SourceFileCount int64 `json:"source_file_count,omitempty"`
}

Progress is the resumable migration cursor: which source/target schema versions this run is bridging, the last table + rowid successfully committed, and whether the run is still in progress or done.

type Report

type Report struct {
	Nodes TableCounts
	Files TableCounts
	Edges TableCounts

	// Dangling lists every non-exempt edge endpoint that failed to
	// resolve, found before any --drop-dangling deletion.
	Dangling []DanglingEdge

	// Dropped counts dangling edges actually deleted under --drop-dangling.
	Dropped int
}

Report is the D-09 structural-invariant pass's result: per-table count reconciliation plus the referential-integrity scan's findings. The caller (07-06) gates Meta.healthy=true on validate returning a nil error (D-10).

type Result

type Result struct {
	Nodes, Edges, Files int64
	Resumed             bool
	HealthMessage       string
	Report              Report
}

Result summarizes a completed (or resumed-to-completion) migration run: final record counts (read back from the migrated store, so they reflect this run's writes plus anything already committed from a prior interrupted attempt), whether this call resumed a prior in-progress run, the stamped Meta.health_message, and the full D-09 validation Report.

func Run

func Run(from, to string, opts Options) (Result, error)

Run converts the TS CodeGraph SQLite index at from into a healthy new-format store at to. from may be a TS .codegraph/ directory (the source *.db is auto-detected via FindDBFile) or a direct path to the *.db file. to is the final new-format .codegraph/ directory path — Run writes into a deterministic sibling partial store first and only replaces to via an atomic directory swap once validate (D-09) passes (D-07/D-10). Every error is wrapped with a "migrate: ..." prefix and returned — never swallowed.

type Source

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

Source is a read-only handle onto a TS CodeGraph SQLite index.

func OpenSource

func OpenSource(dbPath string) (*Source, error)

OpenSource opens dbPath read-only via the modernc.org/sqlite driver. The DSN sets mode=ro (SQLite URI open mode: read-only, fails if the file cannot be opened read-only) and _pragma=query_only(1) (rejects all writes at the SQLite layer) — belt-and-suspenders so the source can never be mutated and no -wal/-shm sidecar is created (D-08 non-destructive-to- source).

func (*Source) Close

func (s *Source) Close() error

Close releases the underlying database handle. It is idempotent: a second call is a no-op. CR-01: Run closes the source explicitly before the atomic directory swap (an open source handle inside the swapped directory breaks os.Rename on Windows), and a deferred Close still runs on every error path — the idempotency guard makes that double-close safe.

func (*Source) Closed

func (s *Source) Closed() bool

Closed reports whether Close has been called. Used by the CR-01 regression test to assert the source handle is released before atomicSwapDir runs (Windows refuses to rename a directory that still contains an open handle).

func (*Source) CountDistinctEdges

func (s *Source) CountDistinctEdges() (int64, error)

CountDistinctEdges returns the number of distinct (source, kind, target) tuples in edges — the count reconciliation (D-09.1) must compare against this, not raw row count, because two TS edges sharing (source,kind,target) but differing only in (line,col) collapse to one stored edge in the new format's key scheme (07-RESEARCH.md §Validation Invariants).

func (*Source) CountRows

func (s *Source) CountRows(table string) (int64, error)

CountRows returns SELECT count(*) FROM table for an allow-listed table.

func (*Source) DetectTS

func (s *Source) DetectTS() error

DetectTS probes sqlite_master for the three tables that make a SQLite file a genuine TS CodeGraph source. Returns ErrNotATSSource if any are absent.

func (*Source) ScanTable

func (s *Source) ScanTable(table string, afterRowID int64, fn func(rowid int64, row map[string]any) error) error

ScanTable streams rows from an allow-listed table (files/nodes/edges), ordered ascending by rowid, restricted to rowid > afterRowID (the resume cursor — D-06). Each row is scanned into a map[string]any keyed by column name, built from the intersection of wantedColumns[table] and the columns actually present (defensive read, D-09.4), then passed to fn. ScanTable returns rows.Err() after the loop — the mandatory fail-loud check mirroring internal/graphstore/export.go's exportNamespace "return iter.Error()" idiom (07-RESEARCH.md Pitfall 2).

func (*Source) SchemaVersion

func (s *Source) SchemaVersion() (int, error)

SchemaVersion returns max(schema_versions.version), the observed source schema version. It returns ErrUnsupportedSchemaVersion (wrapping the observed value) when that version falls outside [minSupportedSchemaVersion, maxSupportedSchemaVersion], or when the table has no rows.

type TableCounts

type TableCounts struct {
	Source   int64
	Migrated int64
}

TableCounts holds one table/kind's source row count next to its migrated record count. For Edges, Source is the DISTINCT(source,kind,target) count (D-09.1) — never the raw source row count, because the Pebble edge key omits line/col and collapses same-triple rows (keys.go's edgeKey doc).

Directories

Path Synopsis
Package migratetest provides an in-Go SQLite fixture-reconstruction harness for internal/migrate tests.
Package migratetest provides an in-Go SQLite fixture-reconstruction harness for internal/migrate tests.

Jump to

Keyboard shortcuts

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