executor

package
v0.1.9 Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2025 License: GPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package executor provides migration execution functionality for ClickHouse databases.

The executor package handles the safe, atomic execution of database migrations with comprehensive error handling, progress tracking, and integrity verification. It integrates with the existing revision tracking system to maintain a complete audit trail of migration execution.

Core Components

The package provides the Executor type for migration execution and supporting types for configuration and result handling:

  • Executor: Main execution engine for applying migrations
  • Config: Configuration options for executor creation
  • ExecutionResult: Detailed results of migration execution
  • ExecutionStatus: Status enumeration for migration outcomes

Key Features

  • Statement-by-statement execution with transaction safety
  • Automatic bootstrap of housekeeper.revisions infrastructure
  • Progress tracking and comprehensive error recovery
  • Hash-based integrity verification
  • Integration with existing revision and migration systems
  • Cluster-aware execution with proper ON CLUSTER handling

Usage Example

// Create executor with ClickHouse client
executor := executor.New(executor.Config{
	ClickHouse:         clickhouseClient,
	Formatter:          format.New(format.Defaults),
	HousekeeperVersion: "1.0.0",
})

// Load migrations from directory
migrationDir, err := migrator.LoadMigrationDir(os.DirFS("./migrations"))
if err != nil {
	log.Fatal(err)
}

// Execute pending migrations
results, err := executor.Execute(ctx, migrationDir.Migrations)
if err != nil {
	log.Fatal(err)
}

// Process results
for _, result := range results {
	switch result.Status {
	case executor.StatusSuccess:
		fmt.Printf("✓ %s completed in %v\n", result.Version, result.ExecutionTime)
	case executor.StatusFailed:
		fmt.Printf("✗ %s failed: %v\n", result.Version, result.Error)
	case executor.StatusSkipped:
		fmt.Printf("- %s already applied\n", result.Version)
	}
}

Bootstrap Handling

The executor automatically handles the bootstrap process for new ClickHouse instances that don't have the housekeeper migration tracking infrastructure:

  • Detects if housekeeper database and revisions table exist
  • Creates missing infrastructure automatically before migration execution
  • Uses IF NOT EXISTS clauses for safe, idempotent bootstrap operations
  • Handles the special case where revisions table doesn't exist on initial setup

Error Handling and Recovery

The executor provides robust error handling with detailed context:

  • Statement-level error reporting with exact SQL and position
  • Partial execution tracking for migration recovery scenarios
  • Comprehensive revision records for failed migrations
  • Safe execution termination on first failure to prevent cascade issues

Integration with Revision System

The executor seamlessly integrates with the existing pkg/migrator revision tracking system:

  • Loads existing revisions to determine pending migrations
  • Creates comprehensive revision records for all executions
  • Records timing, error information, and integrity hashes
  • Supports both StandardRevision and SnapshotRevision types
  • Maintains compatibility with existing revision query methods

Testing and Development

The package is designed with testing in mind and includes:

  • Interface-based ClickHouse client for easy mocking
  • Comprehensive test coverage with testcontainers integration
  • Support for dry-run execution modes
  • Integration with existing Housekeeper test infrastructure

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClickHouse

type ClickHouse interface {
	Query(context.Context, string, ...any) (driver.Rows, error)
	Exec(context.Context, string, ...any) error
}

ClickHouse defines the interface for ClickHouse database operations required by the migration executor.

type Config

type Config struct {
	// ClickHouse client for database operations
	ClickHouse ClickHouse

	// Formatter for generating clean SQL output
	Formatter *format.Formatter

	// HousekeeperVersion to record in revision entries
	HousekeeperVersion string
}

Config contains configuration options for creating a new Executor.

type ExecutionResult

type ExecutionResult struct {
	// Version is the migration version that was executed
	Version string

	// Status indicates the outcome of the migration execution
	Status ExecutionStatus

	// Error contains any error that occurred during execution
	Error error

	// ExecutionTime records how long the migration took to execute
	ExecutionTime time.Duration

	// StatementsApplied indicates how many statements were successfully executed
	StatementsApplied int

	// TotalStatements is the total number of statements in the migration
	TotalStatements int

	// Revision contains the revision record that was created for this execution
	Revision *migrator.Revision
}

ExecutionResult contains the result of executing a single migration.

Results provide detailed information about migration execution including timing, success/failure status, and any errors encountered. This information is essential for debugging failed migrations and tracking execution progress.

type ExecutionStatus

type ExecutionStatus string

ExecutionStatus represents the outcome of a migration execution.

const (
	// StatusSuccess indicates the migration was executed successfully
	StatusSuccess ExecutionStatus = "success"

	// StatusFailed indicates the migration execution failed
	StatusFailed ExecutionStatus = "failed"

	// StatusSkipped indicates the migration was skipped (already applied)
	StatusSkipped ExecutionStatus = "skipped"
)

type Executor

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

Executor handles the execution of database migrations against ClickHouse.

The executor provides safe, atomic migration execution with comprehensive error handling, progress tracking, and integrity verification. It integrates with the existing revision tracking system to maintain a complete audit trail of migration execution.

Key features:

  • Statement-by-statement execution with transaction safety
  • Automatic bootstrap of housekeeper.revisions table
  • Progress tracking and error recovery
  • Hash-based integrity verification
  • Integration with existing revision and migration systems

Example usage:

executor := executor.New(executor.Config{
	ClickHouse:         client,
	Formatter:          format.New(format.Defaults),
	HousekeeperVersion: "1.0.0",
})

results, err := executor.Execute(ctx, []*migrator.Migration{migration})
if err != nil {
	log.Fatal(err)
}

for _, result := range results {
	fmt.Printf("Migration %s: %s\n", result.Version, result.Status)
}

func New

func New(config Config) *Executor

New creates a new migration executor with the provided configuration.

The executor requires a ClickHouse client for database operations, a formatter for SQL generation, and the current Housekeeper version for revision tracking.

Example usage:

executor := executor.New(executor.Config{
	ClickHouse:         clickhouseClient,
	Formatter:          format.New(format.Defaults),
	HousekeeperVersion: "1.0.0",
})

func (*Executor) ComputeHashes

func (e *Executor) ComputeHashes(migration *migrator.Migration) (string, []string)

ComputeHashes computes the migration hash and partial hashes for each statement. This method is exported for testing purposes.

func (*Executor) Execute

func (e *Executor) Execute(ctx context.Context, migrations []*migrator.Migration) ([]*ExecutionResult, error)

Execute applies a list of migrations to the ClickHouse database.

This method handles the complete migration execution lifecycle:

  • Ensures housekeeper database and table exist (bootstrap)
  • Loads existing revisions to determine what needs to be executed
  • Executes each migration statement-by-statement with error handling
  • Records revision entries for successful and failed executions
  • Returns detailed execution results for each migration

The execution is atomic per migration - if any statement in a migration fails, the entire migration is marked as failed and execution stops. Previously executed migrations remain applied.

Example usage:

migrations := []*migrator.Migration{migration1, migration2}
results, err := executor.Execute(ctx, migrations)
if err != nil {
	log.Fatal(err)
}

for _, result := range results {
	switch result.Status {
	case executor.StatusSuccess:
		fmt.Printf("✓ %s completed in %v\n", result.Version, result.ExecutionTime)
	case executor.StatusFailed:
		fmt.Printf("✗ %s failed: %v\n", result.Version, result.Error)
	case executor.StatusSkipped:
		fmt.Printf("- %s already applied\n", result.Version)
	}
}

func (*Executor) IsBootstrapped

func (e *Executor) IsBootstrapped(ctx context.Context) (bool, error)

IsBootstrapped checks whether the housekeeper database and revisions table exist.

This method verifies that the migration tracking infrastructure is properly set up and ready for use. It checks for both the housekeeper database and the revisions table within that database.

Example usage:

bootstrapped, err := executor.IsBootstrapped(ctx)
if err != nil {
	log.Fatal(err)
}

if !bootstrapped {
	fmt.Println("Housekeeper infrastructure needs to be initialized")
}

Jump to

Keyboard shortcuts

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