@@ -568,18 +568,37 @@ ErrorCode MigrationManager::BreakGlassReleaseAsyncCopy(const std::string &operat
568568 std::vector<std::vector<ErrorCode>> results;
569569 const auto ec = meta_searcher.BatchCASLocationStatus (
570570 request_context.get (), {record.block_key }, {{std::move (task)}}, results, true );
571- if (ec != EC_OK ) {
572- return ec;
573- }
574- if (results.size () != 1 || results[0 ].size () != 1 ) {
575- return EC_MISMATCH ;
576- }
577- if (results[0 ][0 ] != EC_OK ) {
571+ const auto transition_is_persistent = [&]() {
572+ CacheLocationMapVector location_maps;
573+ const auto get_result =
574+ indexer->GetLocationsFromPersistent (request_context.get (), {record.block_key }, location_maps);
575+ if (get_result.error_codes .size () != 1 || get_result.error_codes [0 ] != EC_OK || location_maps.size () != 1 ) {
576+ return false ;
577+ }
578+ const auto location_iter = location_maps[0 ].find (record.target_location_id );
579+ return location_iter != location_maps[0 ].end () && location_iter->second &&
580+ location_iter->second ->status () == CLS_DELETING &&
581+ !location_iter->second ->has_migration_copy_guard ();
582+ };
583+ const bool cas_applied = ec == EC_OK && results.size () == 1 && results[0 ].size () == 1 && results[0 ][0 ] == EC_OK ;
584+ if (cas_applied) {
585+ // Sync timeout is an ambiguous durability result, not proof that the
586+ // transition failed. Re-read the persistent backend before returning;
587+ // otherwise a retry would CAS guarded WRITING after the first attempt
588+ // had already durably produced guard-free DELETING and cleanup would
589+ // be stranded forever.
590+ if (!indexer->Sync ({record.block_key }) && !transition_is_persistent ()) {
591+ return EC_ERROR ;
592+ }
593+ } else if (!transition_is_persistent ()) {
594+ if (ec != EC_OK ) {
595+ return ec;
596+ }
597+ if (results.size () != 1 || results[0 ].size () != 1 ) {
598+ return EC_MISMATCH ;
599+ }
578600 return results[0 ][0 ];
579601 }
580- if (!indexer->Sync ({record.block_key })) {
581- return EC_ERROR ;
582- }
583602
584603 CopyTaskContext ctx;
585604 ctx.instance_group_name = record.instance_group_name ;
0 commit comments