@@ -906,6 +906,20 @@ static std::string cache_path_for(const FetchArgument &argument,
906906 return " cache/" + key;
907907}
908908
909+ // A caller that is still validating the response must never join an
910+ // immediate-commit fetch for the same resource. The persistent cache key
911+ // remains shared, but the in-flight network result is isolated by commit
912+ // mode so an immediate owner cannot publish a response on behalf of a
913+ // deferred semantic consumer.
914+ static std::string fetch_singleflight_key (const FetchArgument &argument) {
915+ std::string key = build_cache_key (
916+ argument.url , argument.proxy , argument.request_headers ,
917+ argument.context , global.customOpenClashRulesFallback );
918+ key += " \n defer-cache-commit:" ;
919+ key += argument.defer_cache_commit ? ' 1' : ' 0' ;
920+ return key;
921+ }
922+
909923static bool read_cache_candidate (const std::string &path,
910924 const std::string &header_path,
911925 unsigned int cache_ttl,
@@ -1194,9 +1208,7 @@ int fetchRemote(const FetchArgument &argument, FetchOutcome &outcome) {
11941208 return outcome.status_code ;
11951209 }
11961210
1197- const std::string key = build_cache_key (
1198- argument.url , argument.proxy , argument.request_headers ,
1199- argument.context , global.customOpenClashRulesFallback );
1211+ const std::string key = fetch_singleflight_key (argument);
12001212 std::shared_future<CacheFetchResult> fetch_future;
12011213 std::shared_ptr<std::promise<CacheFetchResult>> fetch_promise;
12021214 bool owner = false ;
0 commit comments