public async Task <RemoteUpdateResult> UpdateAsync(RemoteUpdateResult lastResult, CancellationToken cancellationToken) { if (!enabled) { return(CreateEmptyResult(lastResult)); } var request = CreateRequest(lastResult?.Version); var requestPriority = lastResult == null ? RequestPriority.Critical : RequestPriority.Ordinary; var requestResult = await client.SendAsync(request, priority : requestPriority, cancellationToken : cancellationToken).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { throw new OperationCanceledException(); } var updateResult = TryHandleFailure(requestResult, lastResult); if (updateResult != null) { return(updateResult); } switch (requestResult.Response.Code) { case ResponseCode.NotModified: return(HandleNotModifiedResponse(lastResult)); case ResponseCode.Ok: return(HandleSuccessResponse(lastResult, requestResult.Response, requestResult.Replica)); } throw NoAcceptableResponseException(requestResult); }
private RemoteUpdateResult HandleSuccessResponse(RemoteUpdateResult lastUpdateResult, Response response, Uri replica) { if (!response.HasContent) { throw Empty200ResponseException(); } if (response.Headers.LastModified == null) { throw MissingLastModifiedHeaderException(); } var version = DateTime.Parse(response.Headers.LastModified, null, DateTimeStyles.AssumeUniversal).ToUniversalTime(); if (lastUpdateResult != null && version <= lastUpdateResult.Version) { if (version < lastUpdateResult.Version) { LogStaleVersion(version, lastUpdateResult.Version); } return(new RemoteUpdateResult(false, lastUpdateResult.Tree, lastUpdateResult.Version)); } var tree = new RemoteTree(response.Content.ToArray(), TreeSerializers.V1); LogReceivedNewZone(tree, version, replica); return(new RemoteUpdateResult(true, tree, version)); }
private RemoteUpdateResult HandleNotModifiedResponse(RemoteUpdateResult lastUpdateResult) { if (lastUpdateResult == null) { throw UnexpectedNotModifiedResponseException(); } return(new RemoteUpdateResult(false, lastUpdateResult.Tree, lastUpdateResult.Version)); }
private RemoteUpdateResult TryHandleFailure(ClusterResult requestResult, RemoteUpdateResult lastUpdateResult) { switch (requestResult.Status) { case ClusterResultStatus.ReplicasNotFound: // (iloktionov): If no replicas were resolved during update and we haven't seen any non-trivial settings earlier, // (iloktionov): we just silently assume CC is not deployed in current environment and return empty settings. // (tsup): We make assumptions above in case we are not forced to assume that cluster config is deployed. if (lastUpdateResult?.Tree == null && !assumeClusterConfigDeployed) { if (lastUpdateResult == null) { LogAssumingNoServer(); } return(CreateEmptyResult(lastUpdateResult)); } break; case ClusterResultStatus.ReplicasExhausted: // (iloktionov): Getting here means that no replica returned a 200 or 304 response. // (iloktionov): If at least some of them responded with 404, it's reasonably safe to assume that zone does not exist. if (requestResult.ReplicaResults.Any(r => r.Response.Code == ResponseCode.NotFound)) { var updateResult = CreateEmptyResult(lastUpdateResult); if (updateResult.Changed) { LogZoneDoesNotExist(); } return(updateResult); } break; } return(null); }
private static RemoteUpdateResult CreateEmptyResult([CanBeNull] RemoteUpdateResult lastResult) => new RemoteUpdateResult(lastResult?.Version != EmptyResultVersion, null, EmptyResultVersion);