Skip to content

UploadTracker

methodic.UploadTracker

UploadTracker(db_path: str | Path = 'upload_state.db')

Tracks upload state in a local SQLite database.

Thread-safe via WAL mode. Multiple producers can register files concurrently; the background upload thread drains the queue.

The tracker is passive storage — it doesn't gate work. Atomicity at the asset level (an asset is invisible until all components ship) is enforced by the Chronicle backend's pending → ready finalize state machine, not here. The tracker provides two things: batch-atomic registration via SQLite transactions, and persistent state so a restarted process can resume incomplete uploads.

Caller requirement: register all components for a given asset_id in a SINGLE register_components() batch. Splitting registration across calls races against all_components_completed() — that check returns true once every row currently in the table is COMPLETED, with no notion of "components still to come". A second batch registered after the first has already finalized lands too late: the asset is already ready with only the first batch's components. register_and_upload_async() on Client handles this for you by registering the full component list in one shot.

all_components_completed

all_components_completed(asset_id: str) -> bool

Check if all components for an asset are in COMPLETED state.

get_incomplete

get_incomplete() -> list[PendingUpload]

Return all rows that are not COMPLETED.

get_latest_checkpoint_path

get_latest_checkpoint_path() -> str | None

Get the local_path of the most recently registered checkpoint asset.

Returns the local_path of any component from the latest checkpoint asset (by created_at). The checkpoint directory is the parent of any component file. Returns None if no checkpoints are registered.

Used for in-container crash recovery — the latest registered checkpoint is the last one fully flushed to disk.

has_registered_assets

has_registered_assets() -> bool

Check if there are any registered assets (indicates a restart).

mark_pending

mark_pending(
    asset_id: str,
    component: str,
    local_path: str,
    size: int | None = None,
    asset_type: str = "unknown",
) -> None

Register a single component as PENDING.

register_components

register_components(
    asset_id: str,
    asset_type: str,
    components: list[tuple[str, str, int | None]],
) -> None

Register all components for an asset as PENDING in a single batch.

Parameters:

Name Type Description Default
asset_id str

Chronicle asset UUID.

required
asset_type str

'checkpoint', 'snapshot', 'visualization', etc.

required
components list[tuple[str, str, int | None]]

List of (component_name, local_path, size) tuples.

required

methodic.PendingUpload dataclass

PendingUpload(
    asset_id: str,
    asset_type: str,
    component: str,
    local_path: str,
    state: str,
    created_at: str,
)

A component that needs uploading.