Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion sdk/cosmos/azure-cosmos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

#### Features Added
* Added support for N-Region synchronous commit feature - See [PR 47757](https://github.com/Azure/azure-sdk-for-java/pull/47757)
* Added support for Query Advisor feature - See [48160](https://github.com/Azure/azure-sdk-for-java/pull/48160)
* Added support for Query Advisor feature - See [48160](https://github.com/Azure/azure-sdk-for-java/pull/48160)
* Added write availability strategy (hedging) for Per-Partition Automatic Failover (PPAF) single-writer accounts. When a write to the current write region is slow or fails (410/21005, 503/21008, 403/3, 408), the SDK hedges the write to a read region via the existing availability strategy. On success, the PPAF manager records the new region so subsequent writes route directly there. Controlled by `COSMOS.IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF` system property (default: enabled).

#### Breaking Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,11 @@ public void onBeforeSendRequest(RxDocumentServiceRequest request) {
request.requestContext.routeToLocation(this.regionalRoutingContext);
}

// In case PPAF is enabled and a location override exists for the partition key range assigned to the request
// In case PPAF is enabled and a location override exists for the partition key range assigned to the request.
// This also handles PPAF write hedging — when writeRegionRoutingContextForPpafAvailabilityStrategy is set, it creates
// the ConcurrentHashMap entry and routes the request to the target read region.
this.globalPartitionEndpointManagerForPerPartitionAutomaticFailover.tryAddPartitionLevelLocationOverride(request);

this.throttlingRetry.onBeforeSendRequest(request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ public class Configs {
private static final String IS_READ_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF = "COSMOS.IS_READ_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF";
private static final String IS_READ_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF_VARIABLE = "COSMOS_IS_READ_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF";

private static final String DEFAULT_IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF = "true";
private static final String IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF = "COSMOS.IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF";
private static final String IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF_VARIABLE = "COSMOS_IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF";

private static final int DEFAULT_WARN_LEVEL_LOGGING_THRESHOLD_FOR_PPAF = 25;
private static final String WARN_LEVEL_LOGGING_THRESHOLD_FOR_PPAF = "COSMOS.WARN_LEVEL_LOGGING_THRESHOLD_FOR_PPAF";
private static final String WARN_LEVEL_LOGGING_THRESHOLD_FOR_PPAF_VARIABLE = "COSMOS_WARN_LEVEL_LOGGING_THRESHOLD_FOR_PPAF_VARIABLE";
Expand Down Expand Up @@ -1359,6 +1363,16 @@ public static boolean isReadAvailabilityStrategyEnabledWithPpaf() {
return Boolean.parseBoolean(isReadAvailabilityStrategyEnabledWithPpaf);
}

public static boolean isWriteAvailabilityStrategyEnabledWithPpaf() {
String isWriteAvailabilityStrategyEnabledWithPpaf = System.getProperty(
IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF,
firstNonNull(
emptyToNull(System.getenv().get(IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF_VARIABLE)),
DEFAULT_IS_WRITE_AVAILABILITY_STRATEGY_ENABLED_WITH_PPAF));

return Boolean.parseBoolean(isWriteAvailabilityStrategyEnabledWithPpaf);
}

public static String getAadScopeOverride() {
return System.getProperty(
AAD_SCOPE_OVERRIDE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.azure.cosmos.implementation.perPartitionAutomaticFailover.PerPartitionAutomaticFailoverInfoHolder;
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.LocationSpecificHealthContext;
import com.azure.cosmos.implementation.perPartitionCircuitBreaker.PerPartitionCircuitBreakerInfoHolder;
import com.azure.cosmos.implementation.routing.RegionalRoutingContext;

import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -29,6 +30,23 @@ public class CrossRegionAvailabilityContextForRxDocumentServiceRequest {

private final PerPartitionAutomaticFailoverInfoHolder perPartitionAutomaticFailoverInfoHolder;

/**
* For PPAF write hedging on single-writer accounts, this field holds the target
* read region that the hedged write should be routed to. When set, {@code ClientRetryPolicy}
* uses {@code routeToLocation(RegionalRoutingContext)} to force-route the request
* to this region, bypassing the excluded-regions mechanism which cannot route writes
* to read regions on single-writer accounts.
*/
private volatile RegionalRoutingContext writeRegionRoutingContextForPpafAvailabilityStrategy;

/**
* Captures the resolved {@link PartitionKeyRangeWrapper} during
* {@code tryAddPartitionLevelLocationOverride} so the availability strategy
* success callback can persist the failover entry via
* {@code tryRecordSuccessfulWriteHedge}.
*/
private volatile PartitionKeyRangeWrapper resolvedPartitionKeyRangeWrapperForPpafWriteHedge;

public CrossRegionAvailabilityContextForRxDocumentServiceRequest(
FeedOperationContextForCircuitBreaker feedOperationContextForCircuitBreaker,
PointOperationContextForCircuitBreaker pointOperationContextForCircuitBreaker,
Expand Down Expand Up @@ -96,4 +114,20 @@ public void setPerPartitionFailoverInfo(PartitionLevelAutomaticFailoverInfo part
public PerPartitionAutomaticFailoverInfoHolder getPerPartitionAutomaticFailoverInfoHolder() {
return this.perPartitionAutomaticFailoverInfoHolder;
}

public RegionalRoutingContext getWriteRegionRoutingContextForPpafAvailabilityStrategy() {
return this.writeRegionRoutingContextForPpafAvailabilityStrategy;
}

public void setWriteRegionRoutingContextForPpafAvailabilityStrategy(RegionalRoutingContext writeRegionRoutingContextForPpafAvailabilityStrategy) {
this.writeRegionRoutingContextForPpafAvailabilityStrategy = writeRegionRoutingContextForPpafAvailabilityStrategy;
}

public PartitionKeyRangeWrapper getResolvedPartitionKeyRangeWrapperForPpafWriteHedge() {
return this.resolvedPartitionKeyRangeWrapperForPpafWriteHedge;
}

public void setResolvedPartitionKeyRangeWrapperForPpafWriteHedge(PartitionKeyRangeWrapper resolvedPartitionKeyRangeWrapperForPpafWriteHedge) {
this.resolvedPartitionKeyRangeWrapperForPpafWriteHedge = resolvedPartitionKeyRangeWrapperForPpafWriteHedge;
}
}
Loading
Loading