public T GetResult <T>(MessagePayloadDataConverter messageDataConverter, MessagePayloadDataConverter errorDataConverter) { if (this.IsException) { Exception e = null; // do a best-effort attempt at deserializing this exception try { var type = Type.GetType(this.ExceptionType, true); e = (Exception)errorDataConverter.Deserialize(this.Result, type); } catch { } if (e == null) { // Could not deserialize. Let's just wrap it legibly, // to help developers figure out what happened e = new FunctionFailedException($"Entity operation threw {this.ExceptionType}, content = {this.Result}"); } throw e; } else if (this.Result == null) { return(default(T)); } else { return(messageDataConverter.Deserialize <T>(this.Result)); } }
public DurableEntityContext(DurableTaskExtension config, EntityId entity, TaskEntityShim shim) : base(config, entity.EntityName) { this.dataConverter = config.DataConverter; this.self = entity; this.shim = shim; }
public TaskOrchestrationShim(DurableTaskExtension config, DurabilityProvider durabilityProvider, string name) : base(config) { this.dataConverter = config.DataConverter; this.context = new DurableOrchestrationContext(config, durabilityProvider, name); this.outOfProcShim = new OutOfProcOrchestrationShim(this.context); }
internal DurableOrchestrationContext(DurableTaskExtension config, DurabilityProvider durabilityProvider, string functionName) : base(config, functionName) { this.dataConverter = config.DataConverter; this.durabilityProvider = durabilityProvider; this.actionCount = 0; this.maxActionCount = config.Options.MaxOrchestrationActions; }
public TaskEntityShim(DurableTaskExtension config, string schedulerId) : base(config) { this.dataConverter = config.DataConverter; this.SchedulerId = schedulerId; this.EntityId = EntityId.GetEntityIdFromSchedulerId(schedulerId); this.context = new DurableEntityContext(config, this.EntityId, this); }
public DurableEntityContext(DurableTaskExtension config, DurabilityProvider durabilityProvider, EntityId entity, TaskEntityShim shim) : base(config, entity.EntityName) { this.messageDataConverter = config.MessageDataConverter; this.errorDataConverter = config.ErrorDataConverter; this.durabilityProvider = durabilityProvider; this.self = entity; this.shim = shim; }
public TaskEntityShim(DurableTaskExtension config, DurabilityProvider durabilityProvider, string schedulerId) : base(config) { this.messageDataConverter = config.MessageDataConverter; this.errorDataConverter = config.ErrorDataConverter; this.SchedulerId = schedulerId; this.EntityId = EntityId.GetEntityIdFromSchedulerId(schedulerId); this.context = new DurableEntityContext(config, durabilityProvider, this.EntityId, this); }
public HttpApiHandler(DurableTaskExtension config, ILogger logger) { this.config = config; this.messageDataConverter = this.config.MessageDataConverter; this.logger = logger; // The listen URL must not include the path. this.localHttpListener = new LocalHttpListener( config, this.HandleRequestAsync); }
public T GetInput <T>(MessagePayloadDataConverter dataConverter) { try { return(dataConverter.MessageConverter.Deserialize <T>(this.Input)); } catch (Exception e) { throw new EntitySchedulerException($"Failed to deserialize input for operation '{this.Operation}': {e.Message}", e); } }
public object GetInput(Type inputType, MessagePayloadDataConverter dataConverter) { try { return(dataConverter.Deserialize(this.Input, inputType)); } catch (Exception e) { throw new EntitySchedulerException($"Failed to deserialize input for operation '{this.Operation}': {e.Message}", e); } }
public void SetResult(object result, MessagePayloadDataConverter dataConverter) { this.ExceptionType = null; if (result is JToken jtoken) { this.Result = jtoken.ToString(Formatting.None); } else { this.Result = dataConverter.Serialize(result); } }
private async Task <HttpResponseMessage> HandlePostEntityOperationRequestAsync( HttpRequestMessage request, EntityId entityId) { IDurableEntityClient client = this.GetClient(request); string operationName; if (request.Method == HttpMethod.Delete) { operationName = "delete"; } else { operationName = request.GetQueryNameValuePairs()["op"] ?? string.Empty; } if (request.Content == null || request.Content.Headers.ContentLength == 0) { await client.SignalEntityAsync(entityId, operationName); return(request.CreateResponse(HttpStatusCode.Accepted)); } else { string requestContent = await request.Content.ReadAsStringAsync(); string mediaType = request.Content.Headers.ContentType?.MediaType; object operationInput; if (string.Equals(mediaType, "application/json", StringComparison.OrdinalIgnoreCase)) { try { operationInput = MessagePayloadDataConverter.ConvertToJToken(requestContent); } catch (JsonException e) { return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not parse JSON content: " + e.Message)); } } else { operationInput = requestContent; } await client.SignalEntityAsync(entityId, operationName, operationInput); return(request.CreateResponse(HttpStatusCode.Accepted)); } }
public HttpApiHandler(DurableTaskExtension config, ILogger logger) { this.config = config; this.messageDataConverter = this.config.MessageDataConverter; this.logger = logger; // The listen URL must not include the path. var listenUri = new Uri(InternalRpcUri.GetLeftPart(UriPartial.Authority)); this.localHttpListener = new LocalHttpListener( config, listenUri, this.HandleRequestAsync); }
/// <summary> /// Gets the input of the current activity function instance as a <c>JToken</c>. /// </summary> /// <returns> /// The parsed <c>JToken</c> representation of the activity input. /// </returns> internal JToken GetInputAsJson() { if (this.serializedInput != null && this.parsedJsonInput == null) { var objectArray = this.messageDataConverter.Deserialize <object[]>(this.serializedInput); if (objectArray?.Length != 1) { throw new ArgumentException("The serialized input is expected to be an object array with one element."); } this.parsedJsonInput = MessagePayloadDataConverter.ConvertToJToken(this.messageDataConverter.Serialize(objectArray[0])); } return(this.parsedJsonInput); }
private async Task <HttpResponseMessage> HandleRaiseEventRequestAsync( HttpRequestMessage request, string instanceId, string eventName) { IDurableOrchestrationClient client = this.GetClient(request); DurableOrchestrationStatus status = await client.GetStatusAsync(instanceId); if (status == null) { return(request.CreateResponse(HttpStatusCode.NotFound)); } switch (status.RuntimeStatus) { case OrchestrationRuntimeStatus.Failed: case OrchestrationRuntimeStatus.Canceled: case OrchestrationRuntimeStatus.Terminated: case OrchestrationRuntimeStatus.Completed: return(request.CreateResponse(HttpStatusCode.Gone)); } string mediaType = request.Content.Headers.ContentType?.MediaType; if (!string.Equals(mediaType, "application/json", StringComparison.OrdinalIgnoreCase)) { return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Only application/json request content is supported")); } string stringData = await request.Content.ReadAsStringAsync(); object eventData; try { eventData = MessagePayloadDataConverter.ConvertToJToken(stringData); } catch (JsonReaderException e) { return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid JSON content", e)); } await client.RaiseEventAsync(instanceId, eventName, eventData); return(request.CreateResponse(HttpStatusCode.Accepted)); }
internal DurableClient( DurabilityProvider serviceClient, DurableTaskExtension config, HttpApiHandler httpHandler, DurableClientAttribute attribute) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.dataConverter = config.DataConverter; this.client = new TaskHubClient(serviceClient, this.dataConverter); this.durabilityProvider = serviceClient; this.traceHelper = config.TraceHelper; this.httpApiHandler = httpHandler; this.hubName = attribute.TaskHub ?? config.Options.HubName; this.attribute = attribute; }
public void SetInput(object obj, MessagePayloadDataConverter dataConverter) { try { if (obj is JToken jtoken) { this.Input = jtoken.ToString(Formatting.None); } else { this.Input = dataConverter.Serialize(obj); } } catch (Exception e) { throw new EntitySchedulerException($"Failed to serialize input for operation '{this.Operation}': {e.Message}", e); } }
internal DurableClient( DurabilityProvider serviceClient, HttpApiHandler httpHandler, DurableClientAttribute attribute, MessagePayloadDataConverter messageDataConverter, EndToEndTraceHelper traceHelper, DurableTaskOptions durableTaskOptions) { this.messageDataConverter = messageDataConverter; this.client = new TaskHubClient(serviceClient, this.messageDataConverter); this.durabilityProvider = serviceClient; this.traceHelper = traceHelper; this.httpApiHandler = httpHandler; this.durableTaskOptions = durableTaskOptions; this.hubName = attribute.TaskHub ?? this.durableTaskOptions.HubName; this.attribute = attribute; }
private void InitializeForFunctionsV1(ExtensionConfigContext context) { #if FUNCTIONS_V1 context.ApplyConfig(this.Options, "DurableTask"); this.nameResolver = context.Config.NameResolver; this.ResolveAppSettingOptions(); ILogger logger = context.Config.LoggerFactory.CreateLogger(LoggerCategoryName); this.TraceHelper = new EndToEndTraceHelper(logger, this.Options.Tracing.TraceReplayEvents); this.connectionStringResolver = new WebJobsConnectionStringProvider(); this.durabilityProviderFactory = new AzureStorageDurabilityProviderFactory(new OptionsWrapper <DurableTaskOptions>(this.Options), this.connectionStringResolver); this.defaultDurabilityProvider = this.durabilityProviderFactory.GetDurabilityProvider(); this.LifeCycleNotificationHelper = this.CreateLifeCycleNotificationHelper(); var messageSerializerSettingsFactory = new MessageSerializerSettingsFactory(); var errorSerializerSettingsFactory = new ErrorSerializerSettingsFactory(); this.MessageDataConverter = new MessagePayloadDataConverter(messageSerializerSettingsFactory.CreateJsonSerializerSettings(), true); this.ErrorDataConverter = new MessagePayloadDataConverter(errorSerializerSettingsFactory.CreateJsonSerializerSettings(), true); this.HttpApiHandler = new HttpApiHandler(this, logger); #endif }
public void SetExceptionResult(Exception exception, string operation, MessagePayloadDataConverter errorDataConverter) { this.ExceptionType = exception.GetType().AssemblyQualifiedName; try { this.Result = errorDataConverter.Serialize(exception); } catch (Exception) { // sometimes, exceptions cannot be serialized. In that case we create a serializable wrapper // exception which lets the caller know something went wrong. var wrapper = string.IsNullOrEmpty(operation) ? new OperationErrorException($"{this.ExceptionType} while processing operations: {exception.Message}") : new OperationErrorException($"{this.ExceptionType} in operation '{operation}': {exception.Message}"); this.ExceptionType = wrapper.GetType().AssemblyQualifiedName; this.Result = errorDataConverter.Serialize(wrapper); } }
internal static JToken ParseToJToken(string value) { if (value == null) { return(NullJValue); } // Ignore whitespace value = value.Trim(); if (value.Length == 0) { return(string.Empty); } try { return(MessagePayloadDataConverter.ConvertToJToken(value)); } catch (JsonReaderException) { // Return the raw string value as the fallback. This is common in terminate scenarios. return(value); } }
public HttpApiHandler(DurableTaskExtension config, ILogger logger) { this.config = config; this.dataConverter = this.config.DataConverter; this.logger = logger; }
internal DurableActivityContext(DurableTaskExtension config, string instanceId, string serializedInput) { this.dataConverter = config.DataConverter; this.instanceId = instanceId; this.serializedInput = serializedInput; }
private static async Task <DurableOrchestrationStatus> GetDurableOrchestrationStatusAsync(OrchestrationState orchestrationState, TaskHubClient client, bool showHistory, bool showHistoryOutput) { JArray historyArray = null; if (showHistory && orchestrationState.OrchestrationStatus != OrchestrationStatus.Pending) { string history = await client.GetOrchestrationHistoryAsync(orchestrationState.OrchestrationInstance); if (!string.IsNullOrEmpty(history)) { historyArray = MessagePayloadDataConverter.ConvertToJArray(history); var eventMapper = new Dictionary <string, EventIndexDateMapping>(); var indexList = new List <int>(); for (var i = 0; i < historyArray.Count; i++) { JObject historyItem = (JObject)historyArray[i]; if (Enum.TryParse(historyItem["EventType"].Value <string>(), out EventType eventType)) { // Changing the value of EventType from integer to string for better understanding in the history output historyItem["EventType"] = eventType.ToString(); switch (eventType) { case EventType.TaskScheduled: TrackNameAndScheduledTime(historyItem, eventType, i, eventMapper); historyItem.Remove("Version"); historyItem.Remove("Input"); break; case EventType.TaskCompleted: case EventType.TaskFailed: AddScheduledEventDataAndAggregate(ref eventMapper, "TaskScheduled", historyItem, indexList); historyItem["TaskScheduledId"]?.Parent.Remove(); if (!showHistoryOutput && eventType == EventType.TaskCompleted) { historyItem.Remove("Result"); } ConvertOutputToJToken(historyItem, showHistoryOutput && eventType == EventType.TaskCompleted); break; case EventType.SubOrchestrationInstanceCreated: TrackNameAndScheduledTime(historyItem, eventType, i, eventMapper); historyItem.Remove("Version"); historyItem.Remove("Input"); break; case EventType.SubOrchestrationInstanceCompleted: case EventType.SubOrchestrationInstanceFailed: AddScheduledEventDataAndAggregate(ref eventMapper, "SubOrchestrationInstanceCreated", historyItem, indexList); historyItem.Remove("TaskScheduledId"); if (!showHistoryOutput && eventType == EventType.SubOrchestrationInstanceCompleted) { historyItem.Remove("Result"); } ConvertOutputToJToken(historyItem, showHistoryOutput && eventType == EventType.SubOrchestrationInstanceCompleted); break; case EventType.ExecutionStarted: var functionName = historyItem["Name"]; historyItem.Remove("Name"); historyItem["FunctionName"] = functionName; historyItem.Remove("OrchestrationInstance"); historyItem.Remove("ParentInstance"); historyItem.Remove("Version"); historyItem.Remove("Tags"); historyItem.Remove("Input"); break; case EventType.ExecutionCompleted: if (Enum.TryParse(historyItem["OrchestrationStatus"].Value <string>(), out OrchestrationStatus orchestrationStatus)) { historyItem["OrchestrationStatus"] = orchestrationStatus.ToString(); } if (!showHistoryOutput) { historyItem.Remove("Result"); } ConvertOutputToJToken(historyItem, showHistoryOutput); break; case EventType.ExecutionTerminated: historyItem.Remove("Input"); break; case EventType.TimerFired: historyItem.Remove("TimerId"); break; case EventType.EventRaised: historyItem.Remove("Input"); break; case EventType.OrchestratorStarted: case EventType.OrchestratorCompleted: indexList.Add(i); break; } historyItem.Remove("EventId"); historyItem.Remove("IsPlayed"); } } var counter = 0; indexList.Sort(); foreach (var indexValue in indexList) { historyArray.RemoveAt(indexValue - counter); counter++; } } } return(ConvertOrchestrationStateToStatus(orchestrationState, historyArray)); }