com.microsoft.azure.documentdb.internal.directconnectivity.ReplicatedResourceClient Maven / Gradle / Ivy
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*/
package com.microsoft.azure.documentdb.internal.directconnectivity;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import com.microsoft.azure.documentdb.DocumentClientException;
import com.microsoft.azure.documentdb.internal.AuthorizationTokenProvider;
import com.microsoft.azure.documentdb.internal.DatabaseAccountConfigurationProvider;
import com.microsoft.azure.documentdb.internal.DocumentServiceRequest;
import com.microsoft.azure.documentdb.internal.HttpConstants;
import com.microsoft.azure.documentdb.internal.SessionContainer;
class ReplicatedResourceClient {
static final boolean GLOBAL_STRONG_ENABLED = true;
private SessionContainer sessionContainer;
private ConsistencyReader consistencyReader;
private ConsistencyWriter consistencyWriter;
public ReplicatedResourceClient(GlobalAddressResolver globalAddressResolver,
SessionContainer sessionContainer,
TransportClient transportClient,
DatabaseAccountConfigurationProvider databaseAccountConfigurationProvider,
AuthorizationTokenProvider authorizationTokenProvider,
ExecutorService executorService,
boolean useMultipleWriteLocations) {
this.sessionContainer = sessionContainer;
this.consistencyReader = new ConsistencyReader(
globalAddressResolver,
this.sessionContainer,
transportClient,
databaseAccountConfigurationProvider,
authorizationTokenProvider,
executorService);
this.consistencyWriter = new ConsistencyWriter(
globalAddressResolver,
this.sessionContainer,
transportClient,
databaseAccountConfigurationProvider,
authorizationTokenProvider,
executorService,
useMultipleWriteLocations);
}
public StoreResponse invoke(DocumentServiceRequest request) throws DocumentClientException {
try {
switch (request.getOperationType()) {
case Create:
case Replace:
case Delete:
case ExecuteJavaScript:
case Upsert:
case Recreate:
return this.consistencyWriter.write(request);
case Read:
case ReadFeed:
case Query:
case SqlQuery:
case Head:
case HeadFeed:
return this.consistencyReader.read(request);
default:
throw new IllegalStateException("Unsupported operation type");
}
} catch (DocumentClientException e) {
if (e.getStatusCode() == HttpStatus.SC_GONE
&& (e.getSubStatusCode() == null || e.getSubStatusCode() != HttpConstants.SubStatusCodes.COMPLETING_SPLIT)) {
// Clear the session token, because the collection name might be reused.
this.sessionContainer.clearToken(request);
}
if (request.getClientSideRequestStatistics() != null) {
e.setClientSideRequestStatistics(request.getClientSideRequestStatistics());
}
throw e;
}
}
static URI resolvePrimaryUri(DocumentServiceRequest request, AddressCache addressCache) throws DocumentClientException {
AddressInformation[] replicaAddresses = resolveAddresses(request, addressCache);
return resolvePrimaryUri(request, replicaAddresses);
}
static URI resolvePrimaryUri(DocumentServiceRequest request, AddressInformation[] replicaAddresses) throws DocumentClientException {
try {
if (request.getDefaultReplicaIndex() != null) {
if (request.getDefaultReplicaIndex() >= 0
&& request.getDefaultReplicaIndex() < replicaAddresses.length) {
return new URI(replicaAddresses[request.getDefaultReplicaIndex()].getPhysicalUri());
}
} else {
for (int i = 0; i < replicaAddresses.length; i++) {
if (replicaAddresses[i].isPrimary()) {
return new URI(replicaAddresses[i].getPhysicalUri());
}
}
}
} catch (URISyntaxException e) {
throw new IllegalStateException("Invalid replica address");
}
throw new DocumentClientException(HttpStatus.SC_GONE, "The requested resource is no longer available at the server.");
}
static AddressInformation[] resolveAddresses(DocumentServiceRequest request, AddressCache addressCache) throws DocumentClientException {
AddressInformation[] allResolvedAddresses = addressCache.resolve(request);
ArrayList publicResolvedAddresses = new ArrayList();
ArrayList internalResolvedAddresses = new ArrayList();
for (int i = 0; i < allResolvedAddresses.length; i++) {
AddressInformation address = allResolvedAddresses[i];
if (!StringUtils.isEmpty(address.getPhysicalUri())) {
if (address.isPublic()) {
publicResolvedAddresses.add(address);
} else {
internalResolvedAddresses.add(address);
}
}
}
if (internalResolvedAddresses.size() > 0) {
AddressInformation[] result = new AddressInformation[internalResolvedAddresses.size()];
internalResolvedAddresses.toArray(result);
return result;
} else {
AddressInformation[] result = new AddressInformation[publicResolvedAddresses.size()];
publicResolvedAddresses.toArray(result);
return result;
}
}
String getLastReadAddress() {
return consistencyReader.getLastReadAddress();
}
void setLastReadAddress(String lastReadAddress) {
consistencyReader.setLastReadAddress(lastReadAddress);
}
}