/// <summary> /// Get the partition end point info for the given partition key /// Exceptions this may throw TimeoutException, FabricObjectClosedException, more to be discovered /// </summary> /// <param name="key">Get end point for this given partition key</param> /// <param name="timeout">Timeout for the operation to complete</param> /// <returns>Partition Body</returns> private async Task <PartitionInfo> GetEndpointAsync(PartitionKey key, TimeSpan timeout) { PartitionInfo endpoint = null; var parentName = key.ServiceInstanceName; var propertyName = key.PublishedPropertyName("TransportEndpoint"); var getEndpointDelay = 0; var getCompleted = false; // TODO: revisit the timeout behavior of GetPropertyAsync to clarify and adjust accordingly var remainingTimeout = timeout; FabricEvents.Events.GetEndpointProperty("Start@" + this.streamManager.TraceType, key.ToString(), ""); while (!getCompleted) { var beforeGetPropertyAsync = DateTime.UtcNow; try { var property = await this.client.PropertyManager.GetPropertyAsync(parentName, propertyName); endpoint = property.GetValue <byte[]>().Deserialize <PartitionInfo>(); getCompleted = true; } catch (FabricElementNotFoundException) { FabricEvents.Events.GetEndpointProperty("NotFound.Retrying@" + this.streamManager.TraceType, key.ToString(), ""); } catch (FabricTransientException) { FabricEvents.Events.GetEndpointProperty("TransientError.Retrying@" + this.streamManager.TraceType, key.ToString(), ""); } catch (TimeoutException) { FabricEvents.Events.GetEndpointProperty("Timeout.Retrying@" + this.streamManager.TraceType, key.ToString(), ""); } catch (OperationCanceledException) { FabricEvents.Events.GetEndpointProperty("Canceled.Retrying@" + this.streamManager.TraceType, key.ToString(), ""); } catch (FabricException fabricException) { if (fabricException.ErrorCode == FabricErrorCode.CommunicationError) { FabricEvents.Events.GetEndpointProperty("CommunicationError.Retrying@" + this.streamManager.TraceType, key.ToString(), ""); } else { Tracing.WriteExceptionAsError("RegisterEndpointAsync.GetPropertyAsync.UnrecoverableError", fabricException, "{0}", this.tracer); throw; } } catch (Exception otherException) { Tracing.WriteExceptionAsError("RegisterEndpointAsync.GetPropertyAsync.UnrecoverableError", otherException, "{0}", this.tracer); throw; } if (endpoint == null) { var afterGetPropertyAsync = DateTime.UtcNow; remainingTimeout = TimeoutHandler.UpdateTimeout(remainingTimeout, beforeGetPropertyAsync, afterGetPropertyAsync); getEndpointDelay = getEndpointDelay >= StreamConstants.MaxDelayForValidSessionEndpoint ? StreamConstants.MaxDelayForValidSessionEndpoint : getEndpointDelay + StreamConstants.BaseDelayForValidSessionEndpoint; await Task.Delay(getEndpointDelay); } } bool replaced; // Update resolved end points cache lock (this.resolvedEndpointsLock) { replaced = this.resolvedEndpoints.Remove(key); this.resolvedEndpoints.Add(key, endpoint); } if (replaced) { FabricEvents.Events.GetEndpointProperty("FinishReplaced@" + this.streamManager.TraceType, key.ToString(), endpoint.ToString()); } else { FabricEvents.Events.GetEndpointProperty("FinishNew@" + this.streamManager.TraceType, key.ToString(), endpoint.ToString()); } return(endpoint); }
/// <summary> /// Register my(this instance of) service endpoint info (endpoint and era) /// This method is called only once at startup when the service becomes primary /// </summary> /// <param name="key">Partition to register</param> /// <param name="endpoint">Endpoint of the partition</param> /// <param name="era">Era of the partition</param> /// <returns></returns> internal async Task RegisterPartitionAsync(PartitionKey key, string endpoint, Guid era) { var parentName = key.ServiceInstanceName; var propertyName = key.PublishedPropertyName("TransportEndpoint"); var endPointInfo = new PartitionInfo(endpoint, era); FabricEvents.Events.RegisterEndpointProperty("Start@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); await this.RevokeEnpointAsync(key); var putSuccess = false; while (!putSuccess) { try { await this.client.PropertyManager.PutPropertyAsync(parentName, propertyName, endPointInfo.Serialize()); putSuccess = true; } catch (FabricTransientException) { FabricEvents.Events.RegisterEndpointProperty( "TransientException.Retrying@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); } catch (TimeoutException) { FabricEvents.Events.RegisterEndpointProperty( "Timeout.Retrying@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); } catch (OperationCanceledException) { FabricEvents.Events.RegisterEndpointProperty( "Canceled.Retrying@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); } catch (FabricException fabricException) { if (fabricException.ErrorCode == FabricErrorCode.CommunicationError) { FabricEvents.Events.RegisterEndpointProperty( "CommunicationError.Retrying@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); } else { Tracing.WriteExceptionAsError("RegisterEndpointAsync.PutPropertyAsync.UnrecoverableError", fabricException, "{0}", this.tracer); throw; } } catch (Exception otherException) { Tracing.WriteExceptionAsError("RegisterEndpointAsync.PutPropertyAsync.UnrecoverableError", otherException, "{0}", this.tracer); throw; } } FabricEvents.Events.RegisterEndpointProperty("Finish@" + this.streamManager.TraceType, key.ToString(), endPointInfo.ToString()); }