# orca.maintain

> A module of morca's API.

Table maintenance for a project's datasets: snapshot expiry.

The `orca` binary doesn't link iceberg, so expiry runs in a binary of the
project's own that does: `bin/orca_maintain.mojo`,

```mojo
from orca.maintain import maintain_main

def main() raises:
    maintain_main()
```

which `orca expire` and the scheduler's periodic expiry run (it is found as
`$ORCA_MAINTAIN`, beside the `orca` binary, or on `PATH`). Run by hand it
takes the snapshots to keep besides the policy's with `--retain`; `orca
expire` works those out from Postgres (`orca.expiry.retained`) and passes
them, which is how a run that can still resume keeps the snapshots it read
and the ones it committed.

    orca_maintain expire <dataset> [--older-than 30d|12h|90m|<ms>]
        [--keep N] [--retain ID,...] [--if-policy] [--dry-run] [--report]

Without `--older-than` and `--keep` the table's own
`history.expire.max-snapshot-age-ms` and `history.expire.min-snapshots-to-keep`
decide (iceberg's defaults where unset: five days, one snapshot);
`--if-policy` expires nothing when the table has no
`history.expire.max-snapshot-age-ms`, which is how the scheduler leaves
tables orca didn't create alone. An expiry gives a table orca's metadata
defaults (`write.metadata.delete-after-commit.enabled`,
`write.metadata.previous-versions-max`) when it lacks them, so its own
commit already deletes the old metadata files it drops from the log. `--report` lists `metadata/` before and
after, to count its files.

## Structs

### `Expiry`

```mojo
struct Expiry
```

What one dataset's expiry did, for the line `orca_maintain` prints.

Implements: `Copyable`, `Movable`, `Writable`

Fields:

- `dataset: String`
- `skipped: String`: Why nothing was decided (no policy), or empty.
- `result: ExpireResult`
- `snapshots_before: Int`
- `snapshots_after: Int`
- `metadata_files_before: Int`: -1 when not counted (no `--report`).
- `metadata_files_after: Int`
- `log_after: Int`
- `seconds: Float64`

#### `write_to`

```mojo
def write_to(self, mut w: T)
```

## Functions

### `parse_duration_ms`

```mojo
def parse_duration_ms(text: String) -> Int64
```

`30d`, `12h`, `90m`, `45s` or plain milliseconds.

### `expire_dataset`

```mojo
def expire_dataset(dataset: String, older_than_ms: Int64 = Int64(-1), keep: Int = Int(-1), retain: List[Int64] = List(), if_policy: Bool = False, dry_run: Bool = False, report: Bool = False) -> Expiry
```

Expires `dataset`'s snapshots: older than `older_than_ms` ago (or by the table's properties when that is -1), keeping at least `keep` (or the table's `history.expire.min-snapshots-to-keep`) and every snapshot in `retain`. The metadata is committed first, then the files nothing retained points at are deleted.

### `maintain_main`

```mojo
def maintain_main()
```

The `orca_maintain` command (see the module doc).

## Aliases

### `USAGE`

```mojo
comptime USAGE = "usage:\n  orca_maintain expire <dataset> [--older-than 30d|12h|90m|<ms>] [--keep N]\n      [--retain ID,...] [--if-policy] [--dry-run] [--report]"
```
