Skip to content

[manager] add safe asynchronous CopyGA - #307

Open
shaohuaxi wants to merge 4 commits into
mainfrom
feat/async-copyga-safe
Open

[manager] add safe asynchronous CopyGA#307
shaohuaxi wants to merge 4 commits into
mainfrom
feat/async-copyga-safe

Conversation

@shaohuaxi

Copy link
Copy Markdown
Collaborator

Summary

  • add an opt-in asynchronous CopyGA contract and a persistent migration guard that keeps source and destination locations fenced across leader changes
  • fail closed unless the backend proves the operation is terminal and the destination is safe to reuse; add bounded recovery, cancellation, quarantine inspection, and break-glass release paths
  • back off repeatedly failing source locations, and expose bounded submit/query HTTP timing controls for downstream async backends

Safety model

  • a guarded destination cannot be reclaimed by normal deletion, Reclaimer, or background GC
  • the exact source location used by an in-flight copy remains pinned
  • timeouts, ambiguous submit results, lost task records, and incomplete cancellation never authorize destination reuse
  • recovery runs before leader-only traffic is enabled, with bounded scanning and explicit degraded-state reporting

Async execution remains backend opt-in through SupportsAsyncCopy(). Existing open-source storage backends keep their current synchronous behavior until they provide an implementation.

Validation

Validated on the final branch rebased onto the latest main:

  • instance_group_test
  • migration_strategy_test
  • DataStorageManagerTest
  • meta_dummy_backend_test
  • MetaSearcherTest
  • SchedulePlanExecutorTest
  • MigrationManagerTest
  • CacheReclaimerTest
  • CacheGarbageCollectorTest
  • AdminServiceImplTest
  • //kv_cache_manager:kv_cache_manager_bin

The downstream PACE backend adapter and final end-to-end smoke validation are tracked separately.

@qoderai qoderai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This is a large, well-structured PR introducing an opt-in asynchronous CopyGA contract with persistent guard fencing across leader changes. The safety model — fail-closed unless the backend proves terminal+safe_to_reuse_dst, guards surviving in-memory state loss, and recovery before leader-only traffic — is sound and consistently applied.

Strengths:

  • The two-phase callback split (AsyncCopyRemoteSubmitCompletion vs AsyncCopyCompletion) with the remote_submit_future gating recoverability is a clean separation of concerns.
  • Fail-closed semantics are enforced throughout: EC_CORRUPTION on future/malformed guards in MetaDummyBackend::Open, expected_migration_copy_guard_absent CAS guard preventing fence stealing, has_migration_copy_guard() checks in both CacheReclaimer and CacheGarbageCollector.
  • The reordering in RegistryManager::RemoveStorage (drain before delete) and the SetAsyncCopyReferenceChecker hook are correct safety additions.
  • StartMigrationManager() returning ErrorCode and its promotion to the leader recovery barrier before GC/Reclaimer start is the right ordering.
  • Test coverage is thorough: CAS guard ownership, round-trip serialization, quarantine list/break-glass validation, persistent-guard fence tests in both Reclaimer and GC.

Issues flagged inline (7 comments): See individual comments for details. The most substantive ones are:

  1. Potential race on async_copy_reference_checker_ read without the lock in UnRegisterStorage.
  2. The Demote() re-entrancy question for partially-started MigrationManager.
  3. FindPersistentMigrationSourcePin linkage — ensure its declaration is in a shared header.

No duplicate findings relative to prior reviews (this is the first review on this PR).


🤖 Generated by Qoder

Comment thread kv_cache_manager/data_storage/data_storage_manager.cc
Comment thread kv_cache_manager/data_storage/data_storage_manager.cc
Comment thread kv_cache_manager/service/server.cc
Comment thread kv_cache_manager/service/admin_service_impl.cc
Comment thread kv_cache_manager/manager/cache_reclaimer.cc
Comment thread kv_cache_manager/config/migration_strategy.cc
Comment thread kv_cache_manager/service/test/admin_service_impl_test.cc
Comment thread kv_cache_manager/manager/schedule_plan_executor.h
@github-actions github-actions Bot added the ai reviewed AI has reviewed this PR label Aug 26, 2026
@shaohuaxi
shaohuaxi force-pushed the feat/async-copyga-safe branch from 8c1ef00 to 8fd135c Compare August 26, 2026 06:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c1ef00501

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc
Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
@shaohuaxi
shaohuaxi force-pushed the feat/async-copyga-safe branch from 8fd135c to 2b3ba61 Compare August 26, 2026 06:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b3ba6134c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread kv_cache_manager/config/registry_manager.cc Outdated
Comment thread kv_cache_manager/manager/schedule_plan_executor.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc
@shaohuaxi
shaohuaxi force-pushed the feat/async-copyga-safe branch from 2b3ba61 to 32143a4 Compare August 26, 2026 07:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32143a4114

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
Comment thread kv_cache_manager/manager/schedule_plan_executor.cc Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4e3277435

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread kv_cache_manager/manager/migration_manager.cc Outdated
@shaohuaxi
shaohuaxi force-pushed the feat/async-copyga-safe branch from e18ce0f to 2960155 Compare August 26, 2026 08:58
@shaohuaxi

Copy link
Copy Markdown
Collaborator Author

Review-fix history was cleaned up as requested: c4e32774 and e18ce0fa have been squashed into 2960155a ([manager] address asynchronous Copy review findings). All earlier review replies that reference either old SHA are represented by this single replacement commit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2960155a8a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +2619 to +2624
UpdateAsyncCopyGuard(ctx,
ExpectedGuardState(ctx),
MigrationCopyGuardState::MCGS_UNKNOWN,
ctx.async_backend_task_ids,
fail_reason);
MoveAsyncCopyCreditToQuarantine(ctx, fail_reason);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require durable UNKNOWN before publishing runtime quarantine

When an async submission or completion becomes ambiguous while the metadata CAS or Sync is failing, the return value from UpdateAsyncCopyGuard is ignored and the operation is immediately published in the in-memory quarantine and removed from the active table. The durable guard can therefore remain SUBMITTING, ACTIVE, or CANCELLING; BreakGlassReleaseAsyncCopy then cannot match its required durable UNKNOWN state, and the coordinator is no longer monitored until another leader recovery. Keep the task pending and retry/reconcile the transition, and only publish the quarantine record after kAppliedDurably.

Useful? React with 👍 / 👎.

Comment on lines +2595 to +2596
const auto result = cleanup.future.get();
if (result.status != EC_OK) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retry failed physical cleanup before releasing its reference

When an async target/source cleanup finishes with EC_PARTIAL_OK or EC_ERROR, such as after a transient backend Delete failure, the ready future has already been erased and this branch only logs the result. SchedulePlanExecutor::DoLocationDelTask also proceeds to BatchCADLocationStatus regardless of per-URI deletion failures, so metadata identifying the leaked allocation can disappear and no cleanup reference or retry remains. The fresh evidence beyond the prior reference fix is that ready non-OK futures are still discarded; retain/retry failed physical deletions and avoid removing their metadata until the corresponding URIs are deleted.

Useful? React with 👍 / 👎.

Comment on lines +1061 to +1062
if (!remote_result.accepted) {
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Finalize definitively rejected submits during stop

When graceful demotion occurs after the remote-submit future has become ready with accepted=false and acceptance_unknown=false, this branch discards that authoritative no-side-effect result. The later active-task pass sees a handleless SUBMITTING operation and permanently moves it to UNKNOWN quarantine even though the destination is known safe to delete. The fresh evidence beyond the prior accepted-handle fix is that ready rejected results explicitly take this continue; finalize these as pre-submit failures before processing the remaining detached tasks.

Useful? React with 👍 / 👎.

Comment on lines +2048 to +2050
if (UpdateAsyncCopyGuard(
ctx, MigrationCopyGuardState::MCGS_NONE, MigrationCopyGuardState::MCGS_SUBMITTING, {}, "") !=
GuardMutationResult::kAppliedDurably) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revalidate the source after installing its persistent pin

The source snapshot is taken before destination allocation, but the persistent guard that pins that source is only installed here after Create, BatchAddLocation, and the mark query. During this potentially long preparing window, Reclaimer and ordinary deletion protect the active target but see no persistent source pin, so they can transition the serving source to DELETING and physically remove it; submission then still launches the remote Copy from the stale URI. The remaining pre-guard window is distinct from the guarded steady-state admission fix: after installing the guard, re-read and require the exact source identity to remain CLS_SERVING before backend handoff.

Useful? React with 👍 / 👎.

@shaohuaxi
shaohuaxi force-pushed the feat/async-copyga-safe branch from 2960155 to f0ed093 Compare August 26, 2026 10:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0ed093a1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

ctx.dst_location_id.c_str(),
ctx.async_operation_id.c_str(),
fail_reason.c_str());
SubmitTargetLocationDelete(ctx);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reconcile ambiguous pre-submit finalization before cleanup

When a pre-submit failure occurs after the guarded WRITING -> DELETING CAS succeeds but its Sync times out, this calls ordinary deletion and immediately releases ownership. The delete admission path skips an already CLS_DELETING location unless resume_deleting is set, so it can return EC_OK without physical deletion; if the ambiguous CAS later proves durable, the target is guard-free and recovery cannot discover it, leaving its metadata and allocation stranded. Re-read/retry the finalization and submit prepared/resumed deletion when the transition was applied.

Useful? React with 👍 / 👎.

// The in-memory cancellation must not outrun its persistent fence.
// Drop ownership into fail-closed quarantine; a late completion can no
// longer publish or release the target through this process.
CompleteCopyTaskAsUnknown(cancelling_ctx, "cancel_guard_persist_failed");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the original guard state when cancellation CAS fails

If the ACTIVE/SUBMITTING -> CANCELLING update is definitively not applied, this fallback passes a context already marked kCancelling to CompleteCopyTaskAsUnknown. ExpectedGuardState() therefore attempts CANCELLING -> UNKNOWN, while the durable guard remains ACTIVE or SUBMITTING; every subsequent completion retry mismatches the same state and the operation remains active indefinitely until a leader restart. The fallback must transition from the original expected state or restore/reconcile the in-memory state before retrying.

Useful? React with 👍 / 👎.

Comment on lines +359 to +369
if (!all_physical_deletes_succeeded) {
// CLS_DELETING metadata is the retry anchor. Never CAD it while any
// URI may still exist; the owner retains the storage reference and
// resubmits this exact cleanup through resume_deleting admission.
if (result.error_message.empty()) {
result.error_message = "one or more physical storage deletes failed";
}
KVCM_LOG_WARN("retain %zu CLS_DELETING location(s) after physical delete failure for instance %s",
total_locations_to_delete,
task.instance_id.c_str());
return result;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retry failed deletes submitted by Reclaimer and GC

When a physical delete submitted by the ordinary CacheReclaimer or CacheGarbageCollector returns a transient failure, this now preserves the CLS_DELETING metadata and returns a non-OK result, but those callers discard the completed future and release their pending state (CacheReclaimer::HandleDelRes and CacheGarbageCollector::PollInflightDeletes). Their future scans do not select CLS_DELETING locations, and unlike MigrationManager they never resubmit with resume_deleting, so the failed data and metadata remain stranded indefinitely. Add a retry owner for these callers or a general recovery scan for retained deleting locations.

Useful? React with 👍 / 👎.

expected_items,
operation_id,
options,
[completion, expected_items](AsyncCopyBatchResult batch_result) mutable {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify resumed result task IDs before promotion

When a recovered backend returns the expected number of terminal/safe items but associates them with different, duplicated, or reordered task IDs, this callback discards every AsyncCopyItemResult::backend_task_id and reports success based only on count and flags. MigrationManager can consequently promote the target even though the results do not prove completion of the handles persisted in its guard, potentially serving an incompletely copied cache. Capture the expected handle set/order and treat any task-ID mismatch as unknown rather than successful.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai reviewed AI has reviewed this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant