Skip to content

Materialization protocols

The core materialization contract allows explicitly selected adapters to resolve, load, and commit outputs for partitioned assets. These methods do not add persistence to the core or automatically reuse outputs unless an asset declares an adapter and version. See Materialization protocol for the Materialization, MaterializationContext, and MaterializationRecord definitions.

Optional collection capability

MaterializationCollection is a separate optional protocol exported from kazeflow. An adapter can implement it alongside Materialization:

from collections.abc import Awaitable, Sequence

from kazeflow import (
    MaterializationCollection,
    MaterializationContext,
    MaterializationRecord,
)


class MyCollectionAdapter:
    def available(
        self, contexts: Sequence[MaterializationContext]
    ) -> tuple[MaterializationRecord, ...] | Awaitable[tuple[MaterializationRecord, ...]]:
        ...


collection: MaterializationCollection = MyCollectionAdapter()

The protocol is structural. Existing adapters that only implement resolve, load, and commit remain valid. available(contexts) may be synchronous or asynchronous and returns committed records in the order of the explicit selection, omitting identities with no currently published record. It does not enumerate a store, infer keys from history, or automatically include prior runs. The core does not load, aggregate, publish, or change a run result during collection.

FileMaterialization.available validates the whole non-text sequence and rejects duplicate exact identities before reading storage. It follows the same resolve semantics as a single lookup: missing or invalidated entries are omitted, while corrupt, unsupported, incompatible, or unreadable entries fail explicitly. Returned records remain subject to integrity and revocation checks when later passed to load; collection and load do not form a transaction or lock out concurrent writers. See the partial aggregation example for caller-owned aggregation after a failed run.

Optional invalidation capability

MaterializationInvalidation is a separate optional protocol exported from kazeflow. An adapter may implement it in addition to Materialization:

from kazeflow import MaterializationContext, MaterializationInvalidation

class MyAdapter:
    def invalidate(
        self, context: MaterializationContext, *, reason: str = "explicit"
    ) -> None:
        ...

adapter: MaterializationInvalidation = MyAdapter()

The protocol is structural: an adapter does not need to inherit from it. The method may be synchronous or asynchronous and resolves to None. Existing adapters that only provide resolve, load, and commit remain valid; the executor never calls invalidation automatically. It is a caller-directed operation for a complete identity, including asset name, version, partition domain, typed key and presence, and ordered direct input materialization IDs. An adapter owns how the revocation is persisted. For the file adapter's persistent epoch ledger and reasoned diagnostics, see File materialization adapter.

Callers must coordinate and quiesce users of the identity before invalidating it. The protocol does not promise cross-process locking. Invalidation does not imply a cascade to downstream identities, artifact deletion, garbage collection, run resume, or a new run selection. Applications explicitly select work in a later run.