Implement catalog force replacement

This commit is contained in:
2026-06-19 16:39:01 +00:00
parent 4e673dda76
commit 9a2eaf8e5e
13 changed files with 307 additions and 35 deletions

View File

@@ -187,9 +187,9 @@ Reference: [Operations](operations.md#cleanup-and-recovery).
## Destination Has Unmanaged Content
Symptom: `destination has content but no distributor state` or a plan reason containing `fail_unmanaged`.
Symptom: `destination has content but no distributor state`, `destination output path ... exists but is not managed by catalog state`, or a plan reason containing `fail_unmanaged`.
Likely cause: the destination bundle path contains files but no valid `.distributor.json`, so `distributor` will not claim it by default.
Likely cause: the destination bundle path contains files but no valid `.distributor.json`, or a planned output path collides with storage content that valid catalog state does not record. `distributor` will not claim unmanaged content by default.
Diagnostic:
@@ -197,7 +197,7 @@ Diagnostic:
find <destination-path> -maxdepth 2 -print
```
Safe fix: choose an empty destination path, move unrelated files aside, or preview `run --dry-run --force` only after confirming the reported bundle path is safe to replace.
Safe fix: choose an empty destination path, move unrelated files aside, or preview `run --dry-run --force` only after confirming the reported destination bundle path is safe to replace.
Reference: [Operations](operations.md#forced-replacement-workflow).
@@ -214,7 +214,7 @@ cat <destination-path>/.distributor.json
go run ./cmd/distributor inspect <source-root>
```
Safe fix: verify the source and destination are intended to match. Use a separate destination path for unrelated content. For normal managed replacement, configure destination `takeover.mode` to match the intended ownership boundary or configure `transfer.on_conflict: replace`, then preview with `--dry-run`. Use `--force` only for exceptional replacement of unmanaged content or other force-only cases reported as `force_replace`.
Safe fix: verify the source and destination are intended to match. Use a separate destination path for unrelated content. Use `--force` only for exceptional replacement of unmanaged content, invalid state, unsupported future state, or other cases that `run --dry-run --force` reports as `force_replace`.
Reference: [Operations](operations.md#destination-state-and-retry-behavior).
@@ -280,7 +280,7 @@ Reference: [Operations](operations.md#forced-replacement-workflow).
Symptom: dry-run output includes `force_replace`.
Likely cause: the run used `--force`, and planning selected a supported destructive replacement.
Likely cause: the run used `--force`, and catalog planning selected a supported destructive replacement for unmanaged destination content, a planned unmanaged path collision, invalid destination state, or unsupported future destination state.
Diagnostic:
@@ -288,7 +288,7 @@ Diagnostic:
go run ./cmd/distributor run --config <config-path> --dry-run --force
```
Safe fix: inspect the pipeline id, destination id, backend, and bundle path. Proceed only if deleting everything inside that destination bundle path is intended.
Safe fix: inspect the pipeline id, destination id, backend, and bundle path. Confirm the `destination_path` in JSON output, or the fixed-path `target=.` text output, before applying. Proceed only if deleting everything inside that destination bundle path is intended; `force_replace` then writes planned outputs and schema version `4` catalog state.
Reference: [Operations](operations.md#forced-replacement-workflow).
@@ -327,7 +327,7 @@ Reference: [Operations](operations.md#destination-state-and-retry-behavior).
## Shared-Root Unmanaged Path Collision
Symptom: `fail_unmanaged` with a reason like `destination output path ... exists but is not managed by destination state`.
Symptom: `fail_unmanaged` with a reason like `destination output path ... exists but is not managed by catalog state`.
Likely cause: a `state.mode: shared_root` destination planned a new output path that already exists in storage but is not recorded as managed in `.distributor.json`.