[cosmos] Hedging Detection API — public accessors on CosmosDiagnostics + CosmosDiagnosticsContext
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
- #49184 @NaluTripician による — マージされずにクローズ
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
調査の方向性
CosmosDiagnostics.java、CosmosDiagnosticsContext.java、ClientSideRequestStatistics.java に記載された変更から始め、次に RxDocumentClientImpl の availability strategy のエントリポイントと retry-policy ファイルを追跡します。まず RequestedRegionTests.java と HedgingDetectionTests.java を実行し、その後、受け入れ条件、APIView snapshot、Spark connector の回帰テストスイートを検証します。完了とするには、要求されたすべての accessor、tracking、aggregation、およびテストがパスする必要があります。
索引モデルが issue の本文から書いたものです。
説明
Summary
Add a public Hedging Detection API to com.azure.cosmos.CosmosDiagnostics and com.azure.cosmos.CosmosDiagnosticsContext so customers can post-hoc determine whether a successful or failed Cosmos point/feed operation went through cross-region hedging, which regions were dispatched against, and which regions responded. The surface is strictly additive and non-breaking — both CosmosDiagnostics and CosmosDiagnosticsContext are final, so additions are non-breaking by construction.
This is part of a cross-SDK feature being implemented in parallel across .NET, Java, and Python (with a spec-only deliverable for Rust). See cross-SDK design doc "Hedging Detection API - Technical Design - Final" (2026-05) for the contract.
Public API additions
package com.azure.cosmos.models;
public final class RequestedRegion {
public RequestedRegion(String regionName, RequestedRegionReason reason); // null-guards on regionName
public String getRegionName();
public RequestedRegionReason getReason();
@Override public boolean equals(Object o);
@Override public int hashCode();
@Override public String toString(); // "<regionName>:<REASON>"
}
public enum RequestedRegionReason {
INITIAL,
OPERATION_RETRY,
TRANSPORT_RETRY, // reserved
HEDGING,
REGION_FAILOVER,
CIRCUIT_BREAKER_PROBE, // tied to upstream PRs #45197 / #45267 / #46477 / #48421
}
package com.azure.cosmos;
public final class CosmosDiagnostics {
// existing members unchanged
public boolean isHedgingStarted();
public List<RequestedRegion> getRequestedRegions(); // unmodifiable snapshot
public List<String> getRespondedRegions(); // unmodifiable snapshot, arrival order, duplicates allowed
}
public final class CosmosDiagnosticsContext {
// existing members unchanged
public boolean isHedgingStarted(); // aggregates across children
public List<RequestedRegion> getRequestedRegions(); // aggregates across children (same pattern as getContactedRegionNames)
public List<String> getRespondedRegions(); // aggregates across children
}
Internal state lives on ClientSideRequestStatistics: private final Object regionLock = new Object(); + List<RequestedRegion> requestedRegions + List<String> respondedRegions + boolean hedgingStarted. All three guarded by the same lock — reads AND writes acquire the lock so any reader observes both writes or neither. Bridge accessor ImplementationBridgeHelpers.CosmosDiagnosticsAccessor gains a single appendRequestedRegion(diag, entry) method whose implementation writes both the entry and (if reason == HEDGING) sets hedgingStarted = true inside synchronized(stats.regionLock). setHedgingStarted is not a separate bridge surface — the compound-atomicity invariant is enforced from the bridge.
Critical: Reactor operator order
Append the HEDGING entry via .doOnSubscribe(...) attached inside the hedge arm's Mono chain, NOT before Mono.delaySubscription. Operator order matters:
// CORRECT — doOnSubscribe is on the upstream of delaySubscription
Mono<Response> hedgeArm = regionalMono
.doOnSubscribe(s -> bridgeAccessor.appendRequestedRegion(
diag, new RequestedRegion(region, RequestedRegionReason.HEDGING)))
.delaySubscription(threshold, scheduler);
// WRONG — would fire before the delay starts (phantom entry on primary-wins-under-threshold)
Mono<Response> hedgeArm = regionalMono
.delaySubscription(threshold, scheduler)
.doOnSubscribe(s -> bridgeAccessor.appendRequestedRegion(...));
This is the design doc §12 "no phantom entries" contract — see AC2 / AC10.
Acceptance criteria (testable)
- AC1 Single-region client, readItem success, no retries →
isHedgingStarted() == false;getRequestedRegions().size() == 1with reasonINITIAL;getRespondedRegions().size() == 1. - AC2 Multi-region client, hedging enabled (
ThresholdBasedAvailabilityStrategy), primary responds under threshold →isHedgingStarted() == false;getRequestedRegions().size() == 1; no phantomHEDGINGentry. - AC3 Multi-region client, hedging enabled, primary slow, hedge arm wins →
isHedgingStarted() == true;getRequestedRegions()has ≥2 entries including(hedgeRegion, HEDGING);getRespondedRegions()has ≥1 entry. - AC4 410 Gone retry on same region →
getRequestedRegions()includes consecutive entries(region, INITIAL)then(region, OPERATION_RETRY). - AC5 Region failover after endpoint failure →
getRequestedRegions()includes(originalRegion, INITIAL)then(secondaryRegion, REGION_FAILOVER). - AC6 All-regions-down error →
CosmosException.getDiagnostics().getRequestedRegions()non-empty. - AC9 Existing
EndToEndTimeOutWithAvailabilityTest.getContactedRegionNames().size() > 1(:117) and all 33+ assertions inFaultInjectionWithAvailabilityStrategyTests.javacontinue to pass. - AC10 Reactor scheduler / cancellation smoke test — assert (a)
.doOnSubscribe()on each hedge arm fires only afterdelaySubscriptionelapses without cancellation; (b) when the primary completes beforedelaySubscriptionelapses, the hedge arm'sMonois cancelled and.doOnSubscribe()does NOT fire; (c) when.doOnSubscribe()does fire, the append happens on the orchestrator-side scheduler. - AC11 Aggregation —
CosmosDiagnosticsContext.getRequestedRegions()returns the FIFO-ordered union across theConcurrentLinkedDeque<CosmosDiagnostics>children. - AC12 Spark connector regression —
azure-cosmos-spark_3-4_2-12test suite passes locally. - AC13 APIView snapshot diff cleanly shows the additions (no removals; no signature drift).
- AC14 Live multi-region smoke test (≥1) — runs against the team's multi-region test account with hedging enabled (
ThresholdBasedAvailabilityStrategy), injects primary-slow latency via fault-injection, and assertsisHedgingStarted() == true,getRequestedRegions()includes both regions with the secondary taggedHEDGING,getRespondedRegions()includes the secondary region.
Files in scope
- New:
sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/RequestedRegion.java,RequestedRegionReason.java - Modify:
CosmosDiagnostics.java,CosmosDiagnosticsContext.java,ClientSideRequestStatistics.java(state +@JsonIgnoreon new fields — Spark / encryption / Kafka-connect deserialize through this class),ImplementationBridgeHelpers.java(bridge accessor extension),RxDocumentClientImpl.wrapPointOperationWithAvailabilityStrategy:5460+executeFeedOperationWithAvailabilityStrategy:5850,ClientRetryPolicy.refreshLocation/shouldRetryOnEndpointFailureAsync(:245,:298),GoneAndRetryWithRetryPolicy.java:33/:90, PPCB hook (rebase on PRs #45197 / #45267 / #46477 / #48421),sdk/cosmos/azure-cosmos/CHANGELOG.md - Tests: new
RequestedRegionTests.java, newHedgingDetectionTests.java, live-account multi-region test
Out of scope
- Wiring into OpenTelemetry — separate work item.
- Spark connector behavioral changes — only the
@JsonIgnoredefensive annotation lands here. - Cross-SDK companion implementations (.NET, Python, Rust) — tracked in companion issues.
Notes for the implementer
- Full internal spec, landscape research, plan, risk register (
side-effects.json), and questions+answers are available from the workflow author (@NaluTripician) on request — they are team-only and not linked here. - Phase 1 review gate completed on 2026-05-14. Java-specific resolved decisions: shared
regionLockpattern (matches .NET / Python); single bridge accessorappendRequestedRegion(no separatesetHedgingStarted);com.azure.cosmos.modelsplacement for new public types (matchesCosmosItemResponse/FeedResponseprecedent); at least one live multi-region smoke test required. - This issue is being dispatched to the Coding Agent Harness for end-to-end implementation; reviewers may receive a draft PR shortly.
- 主要言語
- Java
- スター
- 2.6k
- フォーク
- 2.2k
- 平均マージ
- 1日 18時間
- マージ済み PR(30日)
- 206
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
Azure/azure-sdk-for-java のほかの issue
-
mgmt, in track 1 migration guide, call out that file-based authentication method is not recommended再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンAzure.Identity
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
Azure/azure-sdk-for-java#48894 ·
メンテナーはふだん 1 日以内に返信
-
[Design] Support External Evaluation Policy (Invoke) in management SDKs対応中かも @weidongxu-microsoft が 5 日前に担当しました。 オープン
Azure/azure-sdk-for-java#50818 · リアクション 2 件 · 担当者 2 名 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] Align OkHttp and Netty handling of HTTP 407 responses after HTTPS tunnel establishment対応中かも @alzimmermsft が 6 日前に担当しました。 オープンAzure.Core Client
Azure/azure-sdk-for-java#50799 · コメント 2 件 · リアクション 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] azure-core-http-netty ignores response timeout when write timeout is disabled対応中かも @alzimmermsft が 6 日前に担当しました。 オープンAzure.Core Client customer-reported needs-team-attention question
Azure/azure-sdk-for-java#50795 · コメント 3 件 · リアクション 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] azure-core-http-vertx: Streaming request bodies hang on Vert.x 5.x (NoSuchMethodError on HttpClientRequest.reset)対応中かも @alzimmermsft が 6 日前に担当しました。 オープンAzure.Core Client customer-reported needs-team-attention question
Azure/azure-sdk-for-java#50793 · コメント 6 件 · リアクション 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
Azure/azure-sdk-for-java の issue をすべて見る
似ている issue
-
area/kotlin
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 75/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
Large page[number] overflows the computed offset and returns the wrong page対応中かも @auraseb が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100