loom.etl.maintenance¶
Delta table maintenance — backend-agnostic vacuum, compact, and Z-Order.
Public API¶
Authoring:
from loom.etl.maintenance import MaintenanceStep, MaintainTable, MaintainSchema
Running:
from loom.etl.maintenance import MaintenanceRunner, MaintenanceReport
Result types:
from loom.etl.maintenance import (
VacuumResult,
OptimizeResult,
TableMaintenanceResult,
MaintenanceError,
)
Backend protocol (for custom implementations):
from loom.etl.maintenance import DeltaTableMaintainer
Operation specs (for custom operations and backends):
from loom.etl.maintenance import (
MaintenanceSpec,
OpSpec,
OperationDeclaration,
VacuumSpec,
CompactSpec,
ZOrderSpec,
)
Example:
class NightlyMaintenance(MaintenanceStep[None]):
operations = [
MaintainSchema("raw").vacuum(retention_hours=168, dry_run=False).compact(),
MaintainTable("staging.orders")
.vacuum(dry_run=False)
.z_order_by(["run_date", "_id"]),
]
runner = MaintenanceRunner.from_config(config)
report = runner.run(NightlyMaintenance)
report.raise_if_errors()
Custom operations¶
An operation is any class implementing OpSpec: a name class
variable, which keys its result in TableMaintenanceResult.op_results,
and an execute(maintainer, uri, location) method returning a
VacuumResult or an OptimizeResult (or a subclass). To run
it, wrap a declaration in an OperationDeclaration whose resolve
appends the op to each MaintenanceSpec:
from dataclasses import dataclass, replace
from typing import ClassVar
from deltalake import DeltaTable
@dataclass(frozen=True)
class CheckpointSpec:
name: ClassVar[str] = "checkpoint"
def execute(self, maintainer, uri, location) -> OptimizeResult:
DeltaTable(uri, storage_options=location.storage_options).create_checkpoint()
return OptimizeResult()
class Checkpointed:
def __init__(self, inner: OperationDeclaration) -> None:
self._inner = inner
def resolve(self, config: StorageConfig) -> list[MaintenanceSpec]:
return [
replace(spec, ops=(*spec.ops, CheckpointSpec()))
for spec in self._inner.resolve(config)
]
class NightlyMaintenance(MaintenanceStep[None]):
operations = [Checkpointed(MaintainSchema("raw").vacuum(dry_run=False))]
- class loom.etl.maintenance.MaintenanceStep[source]¶
Bases:
Generic[ParamsT]Base class for Delta table maintenance steps.
Subclass and declare
operationsas a list ofMaintainTableand/orMaintainSchemainstances.Example:
class NightlyMaintenance(MaintenanceStep[None]): operations = [ MaintainSchema("raw").vacuum(retention_hours=168, dry_run=False).compact(), MaintainTable("staging.orders") .vacuum(dry_run=False) .z_order_by(["run_date", "_id"]), ]
The step is executed via
MaintenanceRunner:runner = MaintenanceRunner.from_config(config) report = runner.run(NightlyMaintenance) report.raise_if_errors()
- operations_for(params)[source]¶
Return the list of operations to execute for this run.
Override to build the list dynamically from params — useful when operations are driven by Prefect deployment parameters instead of being hardcoded at class-definition time.
The default implementation returns the class-level
operationslist (static behaviour, backwards-compatible).- Parameters:
params (ParamsT)
- Return type:
- class loom.etl.maintenance.MaintainTable(table_ref)[source]¶
Bases:
objectDeclare maintenance operations for one explicitly named Delta table.
Example:
MaintainTable("raw.events") .vacuum(retention_hours=168, dry_run=False) .compact()
- Parameters:
table_ref (str) – Logical table reference (e.g.
"raw.events").
- vacuum(retention_hours=None, *, dry_run=True, full=False)[source]¶
Schedule a VACUUM step.
- Parameters:
retention_hours (int | None) – Files older than this are eligible.
Noneuses the table’sdelta.deletedFileRetentionDuration(default 168 h / 7 days).dry_run (bool) – When
True(default), lists files without deleting. Setdry_run=Falseexplicitly for production runs.full (bool) – When
True, also deletes every file under the table directory that the Delta log does not reference and that is older than the retention, whoever wrote it. SeeVacuumSpec.
- Return type:
- compact(target_size=None)[source]¶
Schedule a bin-packing compaction step.
Mutually exclusive with
z_order_by().- Parameters:
target_size (int | None)
- Return type:
- z_order_by(columns, target_size=None)[source]¶
Schedule a Z-Order clustering step.
Mutually exclusive with
compact().- Parameters:
- Return type:
- resolve(config)[source]¶
Implement
OperationDeclaration.- Parameters:
config (StorageConfig)
- Return type:
- class loom.etl.maintenance.MaintainSchema(schema_prefix)[source]¶
Bases:
objectDeclare maintenance operations for all tables under a schema prefix.
Discovery is config-driven:
_expand()filtersStorageConfig.tablesfor routes whosenamestarts with{schema_prefix}.. No filesystem scanning is performed.Example:
MaintainSchema("raw").vacuum(retention_hours=168, dry_run=False).compact()
- Parameters:
schema_prefix (str) – Schema prefix to match (e.g.
"raw"matches"raw.events","raw.orders").
- vacuum(retention_hours=None, *, dry_run=True, full=False)[source]¶
Schedule a VACUUM step for all discovered tables.
Takes the same arguments as
MaintainTable.vacuum().- Parameters:
- Return type:
- compact(target_size=None)[source]¶
Schedule a compaction step for all discovered tables.
Mutually exclusive with
z_order_by().- Parameters:
target_size (int | None)
- Return type:
- z_order_by(columns, target_size=None)[source]¶
Schedule a Z-Order step for all discovered tables.
Mutually exclusive with
compact().- Parameters:
- Return type:
- resolve(config)[source]¶
Implement
OperationDeclaration.- Parameters:
config (StorageConfig)
- Return type:
- class loom.etl.maintenance.MaintenanceRunner(maintainer, locator, config, *, missing_table_policy='skip')[source]¶
Bases:
objectExecute a
MaintenanceStepagainst Delta tables.Construct via
from_config()for the standard delta-rs path:runner = MaintenanceRunner.from_config(config) report = runner.run(NightlyMaintenance) report.raise_if_errors()
- Parameters:
maintainer (DeltaTableMaintainer) – Backend implementation (default:
DeltaRsMaintainer).locator (TableLocator) – Resolves logical table refs to physical
TableLocation.config (StorageConfig) – Full storage config (needed by
MaintainSchemaexpansion andrun_from_config()).missing_table_policy (Literal['skip', 'error']) –
"skip"silently omits tables not present in config (or not yet initialized as Delta tables);"error"raises immediately.
- classmethod from_config(config, *, missing_table_policy='skip')[source]¶
Build a
MaintenanceRunnerfrom aStorageConfig.Uses delta-rs (
deltalakepackage) as the only backend. Callsto_path_locator()which reuses the samePrefixLocator/MappingLocatorlogic as the Polars ETL backend — no private helpers crossed.- Raises:
ValueError – If config has no path routes configured (only catalog/UC refs, which delta-rs cannot resolve directly).
- Parameters:
config (StorageConfig)
missing_table_policy (Literal['skip', 'error'])
- Return type:
- run(step_cls, params=None)[source]¶
Execute all operations declared on step_cls.
MaintainSchemaentries are expanded against the config at run time;MaintainTableentries are compiled directly.- Parameters:
step_cls (type[MaintenanceStep[Any]]) – A
MaintenanceStepsubclass.params (Any) – Reserved for future parameterisation (currently unused).
- Returns:
MaintenanceReportwith per-table results.- Return type:
- run_from_config()[source]¶
Execute maintenance using the
maintenanceblock in StorageConfig.Discovers all tables listed under the configured schema prefixes and applies the vacuum / compact / z-order settings from
StorageConfig.maintenance.Returns an empty
MaintenanceReportwhen nomaintenanceconfig is defined or no matching tables are found.- Return type:
- class loom.etl.maintenance.MaintenanceReport(results=<factory>)[source]¶
Bases:
objectAggregate result of a maintenance run.
- Parameters:
results (list[TableMaintenanceResult]) – Per-table outcomes (one entry per table processed).
- raise_if_errors()[source]¶
Raise
MaintenanceErrorif any table failed.Useful as a Prefect flow gate:
report = runner.run(NightlyMaintenance) report.raise_if_errors()
- Return type:
None
- exception loom.etl.maintenance.MaintenanceError(failed)[source]¶
Bases:
ExceptionRaised by
MaintenanceReport.raise_if_errors()when any table failed.- Parameters:
failed (list[TableMaintenanceResult])
- Return type:
None
- class loom.etl.maintenance.VacuumResult(files_deleted=<factory>)[source]¶
Bases:
objectResult of a VACUUM operation.
- class loom.etl.maintenance.OptimizeResult(num_files_added=0, num_files_removed=0)[source]¶
Bases:
objectResult of a compaction or Z-Order operation.
Uses counts (not lists) — consistent with the
numFilesAdded/numFilesRemovedkeys returned by the deltalake metrics dict.
- class loom.etl.maintenance.TableMaintenanceResult(table_ref, op_results=<factory>, error=None, duration_seconds=0.0)[source]¶
Bases:
objectPer-table maintenance outcome.
- Parameters:
table_ref (str) – Logical table reference (e.g.
"raw.events").op_results (dict[str, VacuumResult | OptimizeResult]) – Keyed results for each op that ran, by
op.name.error (Exception | None) – Exception caught during execution, or
Noneon success.duration_seconds (float) – Wall-clock time for all ops on this table.
- class loom.etl.maintenance.DeltaTableMaintainer(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for executing maintenance operations on a single Delta table.
Implementations receive the full
TableLocationso they can propagatestorage_options,writer_properties, andcommit_propertiesto every delta-rs call — matching the behaviour ofloom.etl.backends.polars._writer.PolarsTargetWriter._write_kwargs().- vacuum(uri, spec, location)[source]¶
Run VACUUM on the table at uri.
- Parameters:
uri (str)
spec (VacuumSpec)
location (TableLocation)
- Return type:
- compact(uri, spec, location)[source]¶
Run bin-packing compaction on the table at uri.
- Parameters:
uri (str)
spec (CompactSpec)
location (TableLocation)
- Return type:
- z_order(uri, spec, location)[source]¶
Run Z-Order clustering on the table at uri.
- Parameters:
uri (str)
spec (ZOrderSpec)
location (TableLocation)
- Return type:
- class loom.etl.maintenance.OperationDeclaration(*args, **kwargs)[source]¶
Bases:
ProtocolUnified interface for declarative operation builders.
Both
MaintainTableandMaintainSchemaimplement this Protocol so the runner can iterate them uniformly without isinstance branching.
- class loom.etl.maintenance.OpSpec(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol implemented by VacuumSpec, CompactSpec, ZOrderSpec — and any future op.
Each spec knows how to dispatch itself against a DeltaTableMaintainer. Adding a new operation type requires only a new spec class; the runner does not change.
- class loom.etl.maintenance.MaintenanceSpec(table_ref, ops=())[source]¶
Bases:
objectThe ops to run, in order, against one table.
resolve()returns one per table; the runner resolvestable_refto a location and runs each op.
- class loom.etl.maintenance.VacuumSpec(retention_hours=None, dry_run=True, full=False)[source]¶
Bases:
objectParameters for a VACUUM operation.
- Parameters:
retention_hours (int | None) – Files older than this are eligible for deletion.
Noneuses the table’sdelta.deletedFileRetentionDurationproperty (default 168 hours / 7 days).dry_run (bool) – When
True(the default), lists eligible files without deleting them. Setdry_run=Falseexplicitly in production.full (bool) – When
True, also deletes every file under the table directory that the Delta log does not reference and that is older than the retention, whoever wrote it; only names starting with an underscore are kept.False(the default) deletes only the files the log records as removed.
- class loom.etl.maintenance.CompactSpec(target_size=None)[source]¶
Bases:
objectParameters for a file compaction (bin-packing) operation.
- Parameters:
target_size (int | None) – Target output file size in bytes.
Nonelets delta-rs choose based on the table’s configuration.