Skip to content

fix: batch snapshot deletes and checkpoint-poisoned replication (#477) - #481

Merged
perfectra1n merged 4 commits into
mainfrom
fix/477-batch-delete-and-checkpoints
Sep 25, 2026
Merged

perfectra1n merged 4 commits into
mainfrom
fix/477-batch-delete-and-checkpoints

Conversation

@perfectra1n

Copy link
Copy Markdown
Collaborator

Fixes #477. It covers all three root causes from the issue, one commit each so they can be reviewed and bisected on their own.

1. Incomplete kopia checkpoints are never treated as snapshots (c318ec23)

kopia snapshot list --json emits incomplete checkpoint manifests even without --incomplete. That flag filters only the text output (see cli/command_snapshot_list.go in kopia 0.23.1). SnapshotListEntry had no incomplete field, so serde dropped the marker. A single stray checkpoint then failed SnapshotReplication's post-verify on every run. It could also be picked as "latest" by restore, verify, catalog discovery and succeeded-snapshot resolution.

  • SnapshotListEntry / DirSummary now carry incomplete, read through incomplete_reason(). It checks the top-level marker or rootEntry.summ, and treats any non-empty reason as incomplete.
  • KopiaClient::snapshot_list / snapshot_list_all are complete-only by default. snapshot_list_all_with_incomplete() is used only for manifest-ID presence checks.
  • Replication skips source checkpoints, never counts them as expected or missing, and reports them in the new status.lastRun.incompleteSkipped. The mover log names their IDs and the Ready message mentions them.
  • The fixture was captured from a real kopia 0.23.1 repository.

2. One kopia invocation per delete batch (6f825bd2)

A snapdel-* Job ran one kopia snapshot delete <id> per member, so the repository was opened and its index loaded once per member. It now does one snapshot list --all and one kopia snapshot delete <id>... --delete per 500 IDs.

  • Partitioning first is mandatory. I confirmed against a real 0.23.1 repository that a multi-ID delete is all-or-nothing, because the write session only flushes on success. One absent ID aborts the whole call, and kopia still logs "Deleting snapshot …" for IDs it then never commits.
  • batch_delete::plan_batch_delete is pure and keeps every legacy per-member rule: absent means already done, and the stale-ID self-heal still sits behind the start_time data-loss gate. Its matcher excludes the member's own recorded ID, which reproduces the post-delete view the legacy path re-listed. Without that exclusion, a mid-rewrite pin pair is ambiguous and the live manifest is orphaned.
  • A retryable bulk failure fails the chunk and leaves the retry to the controller's backoff. It does not fan out one repository open per ID. A non-retryable failure retries each ID alone, and a failed listing fails the Job outright.
  • classify(): the issue's error (failed to open repository … error loading indexes … unexpected EOF) was Unknown. It is now RepositoryUnavailable, and the more specific arms still win.

3. Per-repository cap on delete batch Jobs (dbd0a95f)

Delete batches were documented as single-flight per repository, but nothing enforced it. That is how #477 ended up with about 33 concurrent Jobs on one B2 repository.

  • New field spec.concurrency.maxConcurrentDeleteJobs on Repository / ClusterRepository. Absent means 1. The minimum is 1, enforced by both the schema and the webhook, and there is no unlimited value.
  • pool::DeleteAdmissionLedger does observe → decide → reserve under one lock (the same pattern as AdmissionLedger), per repository and optionally cluster-wide. It replaces the racy throttle_verdict. A reservation never parks its own Job, so a sibling reconcile of the same wave still dedups on the 409.
  • Batch Jobs now have a 30-minute activeDeadlineSeconds. With a cap of 1, the inherited 48 h deadline would let one wedged Job stall a repository's deletions for two days.
  • Batches are truncated to an 80 KiB serialized-member budget, under the 100 KiB work-spec env cap. MAX_BATCH_MEMBERS goes from 200 to 1000. With long source paths, the old 200 cap could already produce a Job that could not be built.
  • Every "already single-flight" claim is corrected, the helm-docs README is regenerated, and ADR-0006 gets an amendment note.

Verification

  • mise run fmt-check, clippy, test (89 test binaries), gen-check, complexity-check (29/29, no growth) and docs are all green.
  • Every commit was built and tested on its own.
  • I mutation-tested the planner and the ledger by breaking each key line on purpose, and every mutation made a test fail.
  • The fake-kopia shim tests count kopia processes: a batch of N costs exactly one list and one delete.
  • e2e on fresh kind clusters, mass_deletion plus snapshot_replication, 17/17 passing:
    • Scenario 6 now hard-asserts single-flight. The slow-mover fixture holds wave 1 live, and wave 2's Job appears only after wave 1 is done.
    • The new scenario 10 checks that maxConcurrentDeleteJobs: 2 really lets two batches run at once, and never more than two.
    • All existing batch and breaker scenarios still pass, including the global throttle and outage retry.

Reporter: happy to have you run the preview images against your repository. They include the bulk delete, which should drain a backlog like yours in seconds per batch.

kopia's `snapshot list --json` emits incomplete checkpoint manifests even
without `--incomplete` (that flag filters only the text output), and
SnapshotListEntry had no `incomplete` field, so serde dropped the marker.
A stray checkpoint from an interrupted `kopia snapshot create` was then
expected by SnapshotReplication's post-verify forever (#477), and could be
picked as "latest" by restore, verify, catalog discovery and
succeeded-snapshot resolution.

- model: SnapshotListEntry/DirSummary gain `incomplete`, read via
  incomplete_reason() (top-level or rootEntry.summ; any non-empty reason).
- client: snapshot_list/snapshot_list_all are complete-only by default;
  snapshot_list_all_with_incomplete() serves manifest-id presence checks.
- replication: key-set kernels ignore incomplete entries; skipped source
  checkpoints are counted in status.lastRun.incompleteSkipped, named in the
  mover log and in the Ready message.
- fixture captured from a real kopia 0.23.1 repository.

Refs #477
A SnapshotDeleteBatch Job ran one `kopia snapshot delete <id>` process per
member, and every process re-opened the repository and reloaded its full
index. On a large remote repository that is minutes per member: #477
measured 17 deletes in 37 minutes versus 1,336 in 15 seconds for one
multi-id call.

The batch is now planned against ONE `snapshot list --all` and deleted with
one `kopia snapshot delete <id>... --delete` per 500 ids. Partitioning first
is mandatory: kopia's multi-id delete is all-or-nothing (its write session
flushes only on success, verified against a real 0.23.1 repository) and one
absent id aborts the whole call.

- batch_delete::plan_batch_delete is pure and keeps every legacy per-member
  semantic: absent = already done, the start_time-gated stale-id self-heal,
  and its matcher now excludes the member's own recorded id (the post-delete
  view the legacy path re-listed; without it a mid-rewrite pair is ambiguous
  and the live manifest is orphaned).
- KopiaClient::snapshot_delete_many never remaps `no snapshots matched`:
  in multi-id form it means nothing was committed.
- A retryable bulk failure fails the chunk for a controller backoff retry
  instead of re-opening the repository once per id; a non-retryable one
  retries each id alone. A failed listing fails the Job outright.
- classify: `failed to open repository`, `error loading indexes` and
  `unexpected EOF` (the #477 backend error) are RepositoryUnavailable, not
  Unknown.

Refs #477
Delete batches were documented as single-flight per repository, but nothing
enforced it: fireable_members let every finalizer reconcile fire the NEXT
wave while earlier ones ran, and the only brake was the cluster-wide,
default-off KOPIUR_MAX_CONCURRENT_DELETE_JOBS - itself a bare
LIST-then-compare. A 4,000-snapshot replication prune became ~33 concurrent
snapdel Jobs against one B2 repository (#477).

- api: Repository/ClusterRepository spec.concurrency.maxConcurrentDeleteJobs
  (absent = 1, minimum 1 in the schema and the webhook; no "unlimited").
- pool::DeleteAdmissionLedger: observe -> decide -> reserve under one lock
  (the AdmissionLedger pattern), capping per repository AND, when set,
  cluster-wide, so concurrent member reconciles cannot each launch a batch.
  Replaces throttle_verdict. A reservation never parks its own Job, so a
  sibling reconcile of the same wave still dedups on the 409.
- batch Jobs get a 30-minute activeDeadlineSeconds: with a cap of 1, the
  inherited 48h deadline would let one wedged Job stall a repository's
  deletions for two days.
- batches truncate to an 80 KiB serialized-member budget (under the 100 KiB
  work-spec env cap) and MAX_BATCH_MEMBERS rises to 1000; the old 200 cap
  could already build an unbuildable Job with long source paths.
- docs: every "already single-flight" claim corrected; ADR-0006 amended.
- e2e: scenario 6 now hard-asserts single-flight with the batch held live
  by the slow mover; new scenario 10 proves a cap of 2 overlaps.

Refs #477
Code review of #481: incompleteSkipped was scoped through
select_identities, which only sees complete snapshots. An identity whose
ONLY manifest is a checkpoint (an interrupted first backup, #477's exact
shape) was therefore never reported, and a checkpoint-only source
short-circuited to a silent NoIdentitiesMatched.

- incomplete_skipped applies the include/exclude matchers to the
  incomplete entries directly (one shared identity rule with
  select_identities), so every matched checkpoint is counted.
- The NoIdentitiesMatched early return carries the count and names it in
  its Ready message.
- StorageStats.snapshotCount's doc now says it counts complete snapshots,
  matching the complete-only listing it is fed from.

Refs #477
@perfectra1n
perfectra1n added this pull request to the merge queue Sep 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 24, 2026
@perfectra1n
perfectra1n added this pull request to the merge queue Sep 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 24, 2026
@perfectra1n
perfectra1n added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 183337c Sep 25, 2026
40 checks passed
@perfectra1n
perfectra1n deleted the fix/477-batch-delete-and-checkpoints branch September 25, 2026 17:11
@sticky-gecko sticky-gecko Bot mentioned this pull request Sep 25, 2026
doonga pushed a commit to greyrock-labs/home-ops that referenced this pull request Sep 25, 2026
….10.9 ➔ 0.10.10) (#280)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/home-operations/charts/kopiur](https://github.com/home-operations/kopiur) | patch | `0.10.9` → `0.10.10` |

---

### Release Notes

<details>
<summary>home-operations/kopiur (ghcr.io/home-operations/charts/kopiur)</summary>

### [`v0.10.10`](https://github.com/home-operations/kopiur/blob/HEAD/CHANGELOG.md#01010-2026-09-25)

[Compare Source](home-operations/kopiur@0.10.9...0.10.10)

##### Bug Fixes

- batch snapshot deletes and checkpoint-poisoned replication ([#&#8203;477](home-operations/kopiur#477)) ([#&#8203;481](home-operations/kopiur#481)) ([183337c](home-operations/kopiur@183337c))
- **container:** update image busybox ([`cac8f90`](home-operations/kopiur@cac8f90) → [`fd7dc98`](home-operations/kopiur@fd7dc98)) ([#&#8203;479](home-operations/kopiur#479)) ([945a106](home-operations/kopiur@945a106))
- **container:** update image busybox ([`dc2d74b`](home-operations/kopiur@dc2d74b) → [`cac8f90`](home-operations/kopiur@cac8f90)) ([#&#8203;478](home-operations/kopiur#478)) ([8531656](home-operations/kopiur@8531656))
- **e2e:** move MinIO/mc to the pgsty fork; preload digest refs via crictl ([#&#8203;485](home-operations/kopiur#485)) ([a4f0233](home-operations/kopiur@a4f0233))
- **rust:** update crate clap (4.6.6 → 4.6.7) ([#&#8203;465](home-operations/kopiur#465)) ([fcddd45](home-operations/kopiur@fcddd45))
- **rust:** update crate rand (0.10.2 → 0.10.3) ([#&#8203;473](home-operations/kopiur#473)) ([026c0f4](home-operations/kopiur@026c0f4))
- **rust:** update crate thiserror (2.0.20 → 2.0.21) ([#&#8203;482](home-operations/kopiur#482)) ([1457622](home-operations/kopiur@1457622))

##### Continuous Integration

- **github-action:** update github-actions ([#&#8203;468](home-operations/kopiur#468)) ([af27b2e](home-operations/kopiur@af27b2e))

##### Miscellaneous Chores

- **github-action:** update action codecov/codecov-action (v7.1.0 → v7.1.1) ([#&#8203;472](home-operations/kopiur#472)) ([5a3f76b](home-operations/kopiur@5a3f76b))
- **mise:** update mise tools ([#&#8203;463](home-operations/kopiur#463)) ([69698aa](home-operations/kopiur@69698aa))
- **mise:** update tool aqua:astral-sh/uv (0.12.15 → 0.12.16) ([#&#8203;474](home-operations/kopiur#474)) ([8a45270](home-operations/kopiur@8a45270))
- **mise:** update tool aqua:astral-sh/uv (0.12.16 → 0.12.17) ([#&#8203;475](home-operations/kopiur#475)) ([b94926b](home-operations/kopiur@b94926b))
- **mise:** update tool node (24.20.0 → v24.21.0) ([#&#8203;457](home-operations/kopiur#457)) ([fc67c05](home-operations/kopiur@fc67c05))
- **mise:** update tool oxfmt (0.66.0 → 0.68.0) ([#&#8203;459](home-operations/kopiur#459)) ([0614d12](home-operations/kopiur@0614d12))
- **mise:** update tool rust (1.98.0 → 1.98.1) ([#&#8203;447](home-operations/kopiur#447)) ([3b2d33e](home-operations/kopiur@3b2d33e))
- **renovate:** inherit the automerge rules from the shared preset ([#&#8203;483](home-operations/kopiur#483)) ([5b9feb6](home-operations/kopiur@5b9feb6))

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/New_York)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.greyrock.io/todd/home-ops/pulls/280
gabrielcosi pushed a commit to gabrielcosi/home-ops that referenced this pull request Sep 25, 2026
….10.9 ➔ 0.10.10) (#931)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/home-operations/charts/kopiur](https://github.com/home-operations/kopiur) | patch | `0.10.9` → `0.10.10` |

---

### Release Notes

<details>
<summary>home-operations/kopiur (ghcr.io/home-operations/charts/kopiur)</summary>

### [`v0.10.10`](https://github.com/home-operations/kopiur/blob/HEAD/CHANGELOG.md#01010-2026-09-25)

[Compare Source](home-operations/kopiur@0.10.9...0.10.10)

##### Bug Fixes

- batch snapshot deletes and checkpoint-poisoned replication ([#&#8203;477](home-operations/kopiur#477)) ([#&#8203;481](home-operations/kopiur#481)) ([183337c](home-operations/kopiur@183337c))
- **container:** update image busybox ([`cac8f90`](home-operations/kopiur@cac8f90) → [`fd7dc98`](home-operations/kopiur@fd7dc98)) ([#&#8203;479](home-operations/kopiur#479)) ([945a106](home-operations/kopiur@945a106))
- **container:** update image busybox ([`dc2d74b`](home-operations/kopiur@dc2d74b) → [`cac8f90`](home-operations/kopiur@cac8f90)) ([#&#8203;478](home-operations/kopiur#478)) ([8531656](home-operations/kopiur@8531656))
- **e2e:** move MinIO/mc to the pgsty fork; preload digest refs via crictl ([#&#8203;485](home-operations/kopiur#485)) ([a4f0233](home-operations/kopiur@a4f0233))
- **rust:** update crate clap (4.6.6 → 4.6.7) ([#&#8203;465](home-operations/kopiur#465)) ([fcddd45](home-operations/kopiur@fcddd45))
- **rust:** update crate rand (0.10.2 → 0.10.3) ([#&#8203;473](home-operations/kopiur#473)) ([026c0f4](home-operations/kopiur@026c0f4))
- **rust:** update crate thiserror (2.0.20 → 2.0.21) ([#&#8203;482](home-operations/kopiur#482)) ([1457622](home-operations/kopiur@1457622))

##### Continuous Integration

- **github-action:** update github-actions ([#&#8203;468](home-operations/kopiur#468)) ([af27b2e](home-operations/kopiur@af27b2e))

##### Miscellaneous Chores

- **github-action:** update action codecov/codecov-action (v7.1.0 → v7.1.1) ([#&#8203;472](home-operations/kopiur#472)) ([5a3f76b](home-operations/kopiur@5a3f76b))
- **mise:** update mise tools ([#&#8203;463](home-operations/kopiur#463)) ([69698aa](home-operations/kopiur@69698aa))
- **mise:** update tool aqua:astral-sh/uv (0.12.15 → 0.12.16) ([#&#8203;474](home-operations/kopiur#474)) ([8a45270](home-operations/kopiur@8a45270))
- **mise:** update tool aqua:astral-sh/uv (0.12.16 → 0.12.17) ([#&#8203;475](home-operations/kopiur#475)) ([b94926b](home-operations/kopiur@b94926b))
- **mise:** update tool node (24.20.0 → v24.21.0) ([#&#8203;457](home-operations/kopiur#457)) ([fc67c05](home-operations/kopiur@fc67c05))
- **mise:** update tool oxfmt (0.66.0 → 0.68.0) ([#&#8203;459](home-operations/kopiur#459)) ([0614d12](home-operations/kopiur@0614d12))
- **mise:** update tool rust (1.98.0 → 1.98.1) ([#&#8203;447](home-operations/kopiur#447)) ([3b2d33e](home-operations/kopiur@3b2d33e))
- **renovate:** inherit the automerge rules from the shared preset ([#&#8203;483](home-operations/kopiur#483)) ([5b9feb6](home-operations/kopiur@5b9feb6))

</details>

---

### Configuration

📅 **Schedule**: (in timezone Europe/Berlin)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.xcd.dev/gabrielcosi/home-ops/pulls/931
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request Sep 26, 2026
….10.9 ➔ 0.10.10) (#2200)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/home-operations/charts/kopiur](https://github.com/home-operations/kopiur) | patch | `0.10.9` → `0.10.10` |

---

> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/567) for more information.

---

### Release Notes

<details>
<summary>home-operations/kopiur (ghcr.io/home-operations/charts/kopiur)</summary>

### [`v0.10.10`](https://github.com/home-operations/kopiur/blob/HEAD/CHANGELOG.md#01010-2026-09-25)

[Compare Source](home-operations/kopiur@0.10.9...0.10.10)

##### Bug Fixes

- batch snapshot deletes and checkpoint-poisoned replication ([#&#8203;477](home-operations/kopiur#477)) ([#&#8203;481](home-operations/kopiur#481)) ([183337c](home-operations/kopiur@183337c))
- **container:** update image busybox ([`cac8f90`](home-operations/kopiur@cac8f90) → [`fd7dc98`](home-operations/kopiur@fd7dc98)) ([#&#8203;479](home-operations/kopiur#479)) ([945a106](home-operations/kopiur@945a106))
- **container:** update image busybox ([`dc2d74b`](home-operations/kopiur@dc2d74b) → [`cac8f90`](home-operations/kopiur@cac8f90)) ([#&#8203;478](home-operations/kopiur#478)) ([8531656](home-operations/kopiur@8531656))
- **e2e:** move MinIO/mc to the pgsty fork; preload digest refs via crictl ([#&#8203;485](home-operations/kopiur#485)) ([a4f0233](home-operations/kopiur@a4f0233))
- **rust:** update crate clap (4.6.6 → 4.6.7) ([#&#8203;465](home-operations/kopiur#465)) ([fcddd45](home-operations/kopiur@fcddd45))
- **rust:** update crate rand (0.10.2 → 0.10.3) ([#&#8203;473](home-operations/kopiur#473)) ([026c0f4](home-operations/kopiur@026c0f4))
- **rust:** update crate thiserror (2.0.20 → 2.0.21) ([#&#8203;482](home-operations/kopiur#482)) ([1457622](home-operations/kopiur@1457622))

##### Continuous Integration

- **github-action:** update github-actions ([#&#8203;468](home-operations/kopiur#468)) ([af27b2e](home-operations/kopiur@af27b2e))

##### Miscellaneous Chores

- **github-action:** update action codecov/codecov-action (v7.1.0 → v7.1.1) ([#&#8203;472](home-operations/kopiur#472)) ([5a3f76b](home-operations/kopiur@5a3f76b))
- **mise:** update mise tools ([#&#8203;463](home-operations/kopiur#463)) ([69698aa](home-operations/kopiur@69698aa))
- **mise:** update tool aqua:astral-sh/uv (0.12.15 → 0.12.16) ([#&#8203;474](home-operations/kopiur#474)) ([8a45270](home-operations/kopiur@8a45270))
- **mise:** update tool aqua:astral-sh/uv (0.12.16 → 0.12.17) ([#&#8203;475](home-operations/kopiur#475)) ([b94926b](home-operations/kopiur@b94926b))
- **mise:** update tool node (24.20.0 → v24.21.0) ([#&#8203;457](home-operations/kopiur#457)) ([fc67c05](home-operations/kopiur@fc67c05))
- **mise:** update tool oxfmt (0.66.0 → 0.68.0) ([#&#8203;459](home-operations/kopiur#459)) ([0614d12](home-operations/kopiur@0614d12))
- **mise:** update tool rust (1.98.0 → 1.98.1) ([#&#8203;447](home-operations/kopiur#447)) ([3b2d33e](home-operations/kopiur@3b2d33e))
- **renovate:** inherit the automerge rules from the shared preset ([#&#8203;483](home-operations/kopiur#483)) ([5b9feb6](home-operations/kopiur@5b9feb6))

</details>

---

### Configuration

📅 **Schedule**: (in timezone Europe/Paris)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDQuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwNC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/2200
perfectra1n added a commit that referenced this pull request Sep 26, 2026
Brings in 0.10.9/0.10.10 (#467 stream sources + streamExec restores, #481
batched deletes, #485 MinIO fork) and the dependency bumps since the branch
last synced.

Most conflicts were main editing code this branch had moved out of
crates/cli into crates/ops; main's edits are re-applied at the new home:

- restore: `RestoreArgs -> RestoreRequest` is now `TryFrom`, with main's
  total `restore_target_from_args` (no `unreachable!`) refusing by name via
  `CliError::UnresolvedRestoreTarget`, since `streamExec` has no flag.
  Main's two target tests move to cli.rs beside the conversion.
- ops snapshot: `mover: None` on the built spec, plus main's stream-policy
  planned-cells test.
- ops doctor: the privileged-movers annotation value is `true`, not `allow`.
- cli error: keep GoneWhileWaiting/AmbiguousTarget in OpsError (moved), add
  main's UnresolvedRestoreTarget.

Semantic conflicts (merged cleanly, did not compile or silently misbehaved):

- kopia fake_shim: main's new test built an `ObjectId` via `.into()`; this
  branch made it a validated newtype, so use `ObjectId::parse`.
- ui: `SnapshotSpec.mover` in a test fixture; exhaustive `RestoreTarget`
  match in a cli test gains `StreamExec`.
- ui policies view: a `stream` source fell through to "(unrecognized
  source)"; it now renders as `stream/<fileName>`, with a test.

Unions: e2e `ws` feature + ui-model dep; e2e scenario list gains both sides'
buckets; mise tool bumps from main keep this branch's pnpm; expand tests
keep both sides' appended cases. Cargo.lock re-points the new crates at
thiserror 2.0.21.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Batch snapshot deletes: one kopia process per member + unbounded per-repo batch Jobs (plus replication expected-set counts incomplete checkpoints)

1 participant