TaskMessage?ProcessWorkflowCompletedTaskDecision( OrchestrationCompleteOrchestratorAction completeOrchestratorAction, OrchestrationRuntimeState runtimeState, bool includeDetails, out bool continuedAsNew) { ExecutionCompletedEvent executionCompletedEvent; continuedAsNew = (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew); if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { executionCompletedEvent = new ContinueAsNewEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result); } else { executionCompletedEvent = new ExecutionCompletedEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result, completeOrchestratorAction.OrchestrationStatus, completeOrchestratorAction.FailureDetails); } runtimeState.AddEvent(executionCompletedEvent); this.logHelper.OrchestrationCompleted(runtimeState, completeOrchestratorAction); TraceHelper.TraceInstance( runtimeState.OrchestrationStatus == OrchestrationStatus.Failed ? TraceEventType.Warning : TraceEventType.Information, "TaskOrchestrationDispatcher-InstanceCompleted", runtimeState.OrchestrationInstance, "Instance Id '{0}' completed in state {1} with result: {2}", runtimeState.OrchestrationInstance, runtimeState.OrchestrationStatus, completeOrchestratorAction.Result); TraceHelper.TraceInstance( TraceEventType.Information, "TaskOrchestrationDispatcher-InstanceCompletionEvents", runtimeState.OrchestrationInstance, () => Utils.EscapeJson(JsonDataConverter.Default.Serialize(runtimeState.GetOrchestrationRuntimeStateDump(), true))); // Check to see if we need to start a new execution if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { var taskMessage = new TaskMessage(); var startedEvent = new ExecutionStartedEvent(-1, completeOrchestratorAction.Result) { OrchestrationInstance = new OrchestrationInstance { InstanceId = runtimeState.OrchestrationInstance !.InstanceId, ExecutionId = Guid.NewGuid().ToString("N") },
void SetMarkerEvents(HistoryEvent historyEvent) { if (historyEvent is ExecutionStartedEvent) { if (ExecutionStartedEvent != null) { throw new InvalidOperationException( "Multiple ExecutionStartedEvent found, potential corruption in state storage"); } ExecutionStartedEvent = (ExecutionStartedEvent)historyEvent; } else if (historyEvent is ExecutionCompletedEvent) { if (ExecutionCompletedEvent != null) { throw new InvalidOperationException( "Multiple ExecutionCompletedEvent found, potential corruption in state storage"); } ExecutionCompletedEvent = (ExecutionCompletedEvent)historyEvent; } }
/// <inheritdoc /> public override async Task UpdateStateAsync(OrchestrationRuntimeState runtimeState, string instanceId, string executionId) { IList <HistoryEvent> newEvents = runtimeState.NewEvents; IList <HistoryEvent> allEvents = runtimeState.Events; var newEventListBuffer = new StringBuilder(4000); var historyEventBatch = new TableBatchOperation(); EventType?orchestratorEventType = null; string eTagValue = this.GetETagValue(instanceId); DynamicTableEntity orchestrationInstanceUpdate = new DynamicTableEntity(instanceId, "") { Properties = { ["CustomStatus"] = new EntityProperty(runtimeState.Status), ["ExecutionId"] = new EntityProperty(executionId), ["LastUpdatedTime"] = new EntityProperty(newEvents.Last().Timestamp), } }; for (int i = 0; i < newEvents.Count; i++) { HistoryEvent historyEvent = newEvents[i]; DynamicTableEntity entity = this.tableEntityConverter.ConvertToTableEntity(historyEvent); await this.CompressLargeMessageAsync(entity); newEventListBuffer.Append(historyEvent.EventType.ToString()).Append(','); // The row key is the sequence number, which represents the chronological ordinal of the event. long sequenceNumber = i + (allEvents.Count - newEvents.Count); entity.RowKey = sequenceNumber.ToString("X16"); entity.PartitionKey = instanceId; entity.Properties["ExecutionId"] = new EntityProperty(executionId); // Replacement can happen if the orchestration episode gets replayed due to a commit failure in one of the steps below. historyEventBatch.InsertOrReplace(entity); // Table storage only supports inserts of up to 100 entities at a time. if (historyEventBatch.Count == 99) { eTagValue = await this.UploadHistoryBatch(instanceId, executionId, historyEventBatch, newEventListBuffer, newEvents.Count, eTagValue); // Reset local state for the next batch newEventListBuffer.Clear(); historyEventBatch.Clear(); } // Monitor for orchestration instance events switch (historyEvent.EventType) { case EventType.ExecutionStarted: orchestratorEventType = historyEvent.EventType; ExecutionStartedEvent executionStartedEvent = (ExecutionStartedEvent)historyEvent; orchestrationInstanceUpdate.Properties["Name"] = new EntityProperty(executionStartedEvent.Name); orchestrationInstanceUpdate.Properties["Version"] = new EntityProperty(executionStartedEvent.Version); orchestrationInstanceUpdate.Properties["CreatedTime"] = new EntityProperty(executionStartedEvent.Timestamp); orchestrationInstanceUpdate.Properties["RuntimeStatus"] = new EntityProperty(OrchestrationStatus.Running.ToString()); this.SetTablePropertyForMessage(entity, orchestrationInstanceUpdate, InputProperty, InputProperty, executionStartedEvent.Input); break; case EventType.ExecutionCompleted: orchestratorEventType = historyEvent.EventType; ExecutionCompletedEvent executionCompleted = (ExecutionCompletedEvent)historyEvent; this.SetTablePropertyForMessage(entity, orchestrationInstanceUpdate, ResultProperty, OutputProperty, executionCompleted.Result); orchestrationInstanceUpdate.Properties["RuntimeStatus"] = new EntityProperty(executionCompleted.OrchestrationStatus.ToString()); break; case EventType.ExecutionTerminated: orchestratorEventType = historyEvent.EventType; ExecutionTerminatedEvent executionTerminatedEvent = (ExecutionTerminatedEvent)historyEvent; this.SetTablePropertyForMessage(entity, orchestrationInstanceUpdate, InputProperty, OutputProperty, executionTerminatedEvent.Input); orchestrationInstanceUpdate.Properties["RuntimeStatus"] = new EntityProperty(OrchestrationStatus.Terminated.ToString()); break; case EventType.ContinueAsNew: orchestratorEventType = historyEvent.EventType; ExecutionCompletedEvent executionCompletedEvent = (ExecutionCompletedEvent)historyEvent; this.SetTablePropertyForMessage(entity, orchestrationInstanceUpdate, ResultProperty, OutputProperty, executionCompletedEvent.Result); orchestrationInstanceUpdate.Properties["RuntimeStatus"] = new EntityProperty(OrchestrationStatus.ContinuedAsNew.ToString()); break; } } // First persistence step is to commit history to the history table. Messages must come after. if (historyEventBatch.Count > 0) { eTagValue = await this.UploadHistoryBatch(instanceId, executionId, historyEventBatch, newEventListBuffer, newEvents.Count, eTagValue); } if (orchestratorEventType == EventType.ExecutionCompleted || orchestratorEventType == EventType.ExecutionFailed || orchestratorEventType == EventType.ExecutionTerminated) { this.eTagValues.TryRemove(instanceId, out _); } else { this.eTagValues[instanceId] = eTagValue; } Stopwatch orchestrationInstanceUpdateStopwatch = Stopwatch.StartNew(); await this.instancesTable.ExecuteAsync(TableOperation.InsertOrMerge(orchestrationInstanceUpdate)); this.stats.StorageRequests.Increment(); this.stats.TableEntitiesWritten.Increment(); AnalyticsEventSource.Log.InstanceStatusUpdate( this.storageAccountName, this.taskHubName, instanceId, executionId, orchestratorEventType?.ToString() ?? string.Empty, orchestrationInstanceUpdateStopwatch.ElapsedMilliseconds); }
HistoryEvent GenerateAbridgedEvent(HistoryEvent evt) { HistoryEvent returnedEvent = evt; if (evt is TaskScheduledEvent) { var sourceEvent = (TaskScheduledEvent) evt; returnedEvent = new TaskScheduledEvent(sourceEvent.EventId) { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, Name = sourceEvent.Name, Version = sourceEvent.Version, Input = "[..snipped..]", }; } else if (evt is TaskCompletedEvent) { var sourceEvent = (TaskCompletedEvent) evt; returnedEvent = new TaskCompletedEvent(sourceEvent.EventId, sourceEvent.TaskScheduledId, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is SubOrchestrationInstanceCreatedEvent) { var sourceEvent = (SubOrchestrationInstanceCreatedEvent) evt; returnedEvent = new SubOrchestrationInstanceCreatedEvent(sourceEvent.EventId) { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, Name = sourceEvent.Name, Version = sourceEvent.Version, Input = "[..snipped..]", }; } else if (evt is SubOrchestrationInstanceCompletedEvent) { var sourceEvent = (SubOrchestrationInstanceCompletedEvent) evt; returnedEvent = new SubOrchestrationInstanceCompletedEvent(sourceEvent.EventId, sourceEvent.TaskScheduledId, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is TaskFailedEvent) { var sourceEvent = (TaskFailedEvent) evt; returnedEvent = new TaskFailedEvent(sourceEvent.EventId, sourceEvent.TaskScheduledId, sourceEvent.Reason, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is SubOrchestrationInstanceFailedEvent) { var sourceEvent = (SubOrchestrationInstanceFailedEvent) evt; returnedEvent = new SubOrchestrationInstanceFailedEvent(sourceEvent.EventId, sourceEvent.TaskScheduledId, sourceEvent.Reason, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is ExecutionStartedEvent) { var sourceEvent = (ExecutionStartedEvent) evt; returnedEvent = new ExecutionStartedEvent(sourceEvent.EventId, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is ExecutionCompletedEvent) { var sourceEvent = (ExecutionCompletedEvent) evt; returnedEvent = new ExecutionCompletedEvent(sourceEvent.EventId, "[..snipped..]", sourceEvent.OrchestrationStatus) { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } else if (evt is ExecutionTerminatedEvent) { var sourceEvent = (ExecutionTerminatedEvent) evt; returnedEvent = new ExecutionTerminatedEvent(sourceEvent.EventId, "[..snipped..]") { Timestamp = sourceEvent.Timestamp, IsPlayed = sourceEvent.IsPlayed, }; } // ContinueAsNewEvent is covered by the ExecutionCompletedEvent block return returnedEvent; }
void SetMarkerEvents(HistoryEvent historyEvent) { if (historyEvent is ExecutionStartedEvent) { if (ExecutionStartedEvent != null) { throw new InvalidOperationException( "Multiple ExecutionStartedEvent found, potential corruption in state storage"); } ExecutionStartedEvent = (ExecutionStartedEvent) historyEvent; } else if (historyEvent is ExecutionCompletedEvent) { if (ExecutionCompletedEvent != null) { throw new InvalidOperationException( "Multiple ExecutionCompletedEvent found, potential corruption in state storage"); } ExecutionCompletedEvent = (ExecutionCompletedEvent) historyEvent; } }
static TaskMessage ProcessWorkflowCompletedTaskDecision( OrchestrationCompleteOrchestratorAction completeOrchestratorAction, OrchestrationRuntimeState runtimeState, bool includeDetails, out bool continuedAsNew) { ExecutionCompletedEvent executionCompletedEvent; continuedAsNew = (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew); if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { executionCompletedEvent = new ContinueAsNewEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result); } else { executionCompletedEvent = new ExecutionCompletedEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result, completeOrchestratorAction.OrchestrationStatus); } runtimeState.AddEvent(executionCompletedEvent); TraceHelper.TraceInstance( runtimeState.OrchestrationStatus == OrchestrationStatus.Failed ? TraceEventType.Warning : TraceEventType.Information, "TaskOrchestrationDispatcher-InstanceCompleted", runtimeState.OrchestrationInstance, "Instance Id '{0}' completed in state {1} with result: {2}", runtimeState.OrchestrationInstance, runtimeState.OrchestrationStatus, completeOrchestratorAction.Result); TraceHelper.TraceInstance( TraceEventType.Information, "TaskOrchestrationDispatcher-InstanceCompletionEvents", runtimeState.OrchestrationInstance, () => Utils.EscapeJson(DataConverter.Serialize(runtimeState.Events, true))); // Check to see if we need to start a new execution if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { var taskMessage = new TaskMessage(); var startedEvent = new ExecutionStartedEvent(-1, completeOrchestratorAction.Result) { OrchestrationInstance = new OrchestrationInstance { InstanceId = runtimeState.OrchestrationInstance.InstanceId, ExecutionId = Guid.NewGuid().ToString("N") }, Tags = runtimeState.Tags, ParentInstance = runtimeState.ParentInstance, Name = runtimeState.Name, Version = completeOrchestratorAction.NewVersion ?? runtimeState.Version }; taskMessage.OrchestrationInstance = startedEvent.OrchestrationInstance; taskMessage.Event = startedEvent; return(taskMessage); } // If this is a Sub Orchestration, and not tagged as fire-and-forget, // then notify the parent by sending a complete message if (runtimeState.ParentInstance != null && !OrchestrationTags.IsTaggedAsFireAndForget(runtimeState.Tags)) { var taskMessage = new TaskMessage(); if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Completed) { var subOrchestrationCompletedEvent = new SubOrchestrationInstanceCompletedEvent(-1, runtimeState.ParentInstance.TaskScheduleId, completeOrchestratorAction.Result); taskMessage.Event = subOrchestrationCompletedEvent; } else if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Failed || completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Terminated) { var subOrchestrationFailedEvent = new SubOrchestrationInstanceFailedEvent(-1, runtimeState.ParentInstance.TaskScheduleId, completeOrchestratorAction.Result, includeDetails ? completeOrchestratorAction.Details : null); taskMessage.Event = subOrchestrationFailedEvent; } if (taskMessage.Event != null) { taskMessage.OrchestrationInstance = runtimeState.ParentInstance.OrchestrationInstance; return(taskMessage); } } return(null); }
static TaskMessage ProcessWorkflowCompletedTaskDecision( OrchestrationCompleteOrchestratorAction completeOrchestratorAction, OrchestrationRuntimeState runtimeState, bool includeDetails, out bool continuedAsNew) { ExecutionCompletedEvent executionCompletedEvent; continuedAsNew = (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew); if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { executionCompletedEvent = new ContinueAsNewEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result); } else { executionCompletedEvent = new ExecutionCompletedEvent(completeOrchestratorAction.Id, completeOrchestratorAction.Result, completeOrchestratorAction.OrchestrationStatus); } runtimeState.AddEvent(executionCompletedEvent); TraceHelper.TraceInstance(TraceEventType.Information, runtimeState.OrchestrationInstance, "Instance Id '{0}' completed in state {1} with result: {2}", runtimeState.OrchestrationInstance, runtimeState.OrchestrationStatus, completeOrchestratorAction.Result); string history = JsonConvert.SerializeObject(runtimeState.Events, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }); TraceHelper.TraceInstance(TraceEventType.Information, runtimeState.OrchestrationInstance, () => Utils.EscapeJson(history)); // Check to see if we need to start a new execution if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { var taskMessage = new TaskMessage(); var startedEvent = new ExecutionStartedEvent(-1, completeOrchestratorAction.Result); startedEvent.OrchestrationInstance = new OrchestrationInstance { InstanceId = runtimeState.OrchestrationInstance.InstanceId, ExecutionId = Guid.NewGuid().ToString("N") }; startedEvent.Tags = runtimeState.Tags; startedEvent.ParentInstance = runtimeState.ParentInstance; startedEvent.Name = runtimeState.Name; startedEvent.Version = completeOrchestratorAction.NewVersion ?? runtimeState.Version; taskMessage.OrchestrationInstance = startedEvent.OrchestrationInstance; taskMessage.Event = startedEvent; return(taskMessage); } // If this is a Sub Orchestration than notify the parent by sending a complete message if (runtimeState.ParentInstance != null) { var taskMessage = new TaskMessage(); if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Completed) { var subOrchestrationCompletedEvent = new SubOrchestrationInstanceCompletedEvent(-1, runtimeState.ParentInstance.TaskScheduleId, completeOrchestratorAction.Result); taskMessage.Event = subOrchestrationCompletedEvent; } else if (completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Failed || completeOrchestratorAction.OrchestrationStatus == OrchestrationStatus.Terminated) { var subOrchestrationFailedEvent = new SubOrchestrationInstanceFailedEvent(-1, runtimeState.ParentInstance.TaskScheduleId, completeOrchestratorAction.Result, includeDetails ? completeOrchestratorAction.Details : null); taskMessage.Event = subOrchestrationFailedEvent; } if (taskMessage.Event != null) { taskMessage.OrchestrationInstance = runtimeState.ParentInstance.OrchestrationInstance; return(taskMessage); } } return(null); }
HistoryEvent GenerateAbridgedEvent(HistoryEvent evt) { HistoryEvent returnedEvent = evt; if (evt is TaskScheduledEvent taskScheduledEvent) { returnedEvent = new TaskScheduledEvent(taskScheduledEvent.EventId) { Timestamp = taskScheduledEvent.Timestamp, IsPlayed = taskScheduledEvent.IsPlayed, Name = taskScheduledEvent.Name, Version = taskScheduledEvent.Version, Input = "[..snipped..]", }; } else if (evt is TaskCompletedEvent taskCompletedEvent) { returnedEvent = new TaskCompletedEvent(taskCompletedEvent.EventId, taskCompletedEvent.TaskScheduledId, "[..snipped..]") { Timestamp = taskCompletedEvent.Timestamp, IsPlayed = taskCompletedEvent.IsPlayed, }; } else if (evt is SubOrchestrationInstanceCreatedEvent subOrchestrationInstanceCreatedEvent) { returnedEvent = new SubOrchestrationInstanceCreatedEvent(subOrchestrationInstanceCreatedEvent.EventId) { Timestamp = subOrchestrationInstanceCreatedEvent.Timestamp, IsPlayed = subOrchestrationInstanceCreatedEvent.IsPlayed, Name = subOrchestrationInstanceCreatedEvent.Name, Version = subOrchestrationInstanceCreatedEvent.Version, Input = "[..snipped..]", }; } else if (evt is SubOrchestrationInstanceCompletedEvent subOrchestrationInstanceCompletedEvent) { returnedEvent = new SubOrchestrationInstanceCompletedEvent(subOrchestrationInstanceCompletedEvent.EventId, subOrchestrationInstanceCompletedEvent.TaskScheduledId, "[..snipped..]") { Timestamp = subOrchestrationInstanceCompletedEvent.Timestamp, IsPlayed = subOrchestrationInstanceCompletedEvent.IsPlayed, }; } else if (evt is TaskFailedEvent taskFailedEvent) { returnedEvent = new TaskFailedEvent(taskFailedEvent.EventId, taskFailedEvent.TaskScheduledId, taskFailedEvent.Reason, "[..snipped..]") { Timestamp = taskFailedEvent.Timestamp, IsPlayed = taskFailedEvent.IsPlayed, }; } else if (evt is SubOrchestrationInstanceFailedEvent subOrchestrationInstanceFailedEvent) { returnedEvent = new SubOrchestrationInstanceFailedEvent(subOrchestrationInstanceFailedEvent.EventId, subOrchestrationInstanceFailedEvent.TaskScheduledId, subOrchestrationInstanceFailedEvent.Reason, "[..snipped..]") { Timestamp = subOrchestrationInstanceFailedEvent.Timestamp, IsPlayed = subOrchestrationInstanceFailedEvent.IsPlayed, }; } else if (evt is ExecutionStartedEvent executionStartedEvent) { returnedEvent = new ExecutionStartedEvent(executionStartedEvent.EventId, "[..snipped..]") { Timestamp = executionStartedEvent.Timestamp, IsPlayed = executionStartedEvent.IsPlayed, }; } else if (evt is ExecutionCompletedEvent executionCompletedEvent) { returnedEvent = new ExecutionCompletedEvent(executionCompletedEvent.EventId, "[..snipped..]", executionCompletedEvent.OrchestrationStatus) { Timestamp = executionCompletedEvent.Timestamp, IsPlayed = executionCompletedEvent.IsPlayed, }; } else if (evt is ExecutionTerminatedEvent executionTerminatedEvent) { returnedEvent = new ExecutionTerminatedEvent(executionTerminatedEvent.EventId, "[..snipped..]") { Timestamp = executionTerminatedEvent.Timestamp, IsPlayed = executionTerminatedEvent.IsPlayed, }; } // ContinueAsNewEvent is covered by the ExecutionCompletedEvent block return(returnedEvent); }
public static HistoryEvent GetHistoryEvent(this DbDataReader reader, bool isOrchestrationHistory = false) { string eventTypeString = (string)reader["EventType"]; if (!Enum.TryParse(eventTypeString, out EventType eventType)) { throw new InvalidOperationException($"Unknown event type '{eventTypeString}'."); } int eventId = GetTaskId(reader); HistoryEvent historyEvent; switch (eventType) { case EventType.ContinueAsNew: historyEvent = new ContinueAsNewEvent(eventId, GetPayloadText(reader)); break; case EventType.EventRaised: historyEvent = new EventRaisedEvent(eventId, GetPayloadText(reader)) { Name = GetName(reader), }; break; case EventType.EventSent: historyEvent = new EventSentEvent(eventId) { Input = GetPayloadText(reader), Name = GetName(reader), InstanceId = GetInstanceId(reader), }; break; case EventType.ExecutionCompleted: historyEvent = new ExecutionCompletedEvent( eventId, result: GetPayloadText(reader), orchestrationStatus: OrchestrationStatus.Completed); break; case EventType.ExecutionFailed: historyEvent = new ExecutionCompletedEvent( eventId, result: GetPayloadText(reader), orchestrationStatus: OrchestrationStatus.Failed); break; case EventType.ExecutionStarted: historyEvent = new ExecutionStartedEvent(eventId, GetPayloadText(reader)) { Name = GetName(reader), OrchestrationInstance = new OrchestrationInstance { InstanceId = GetInstanceId(reader), ExecutionId = GetExecutionId(reader), }, Tags = null, // TODO Version = GetVersion(reader), }; string?parentInstanceId = GetParentInstanceId(reader); if (parentInstanceId != null) { ((ExecutionStartedEvent)historyEvent).ParentInstance = new ParentInstance { OrchestrationInstance = new OrchestrationInstance { InstanceId = parentInstanceId }, TaskScheduleId = GetTaskId(reader) }; } break; case EventType.ExecutionTerminated: historyEvent = new ExecutionTerminatedEvent(eventId, GetPayloadText(reader)); break; case EventType.GenericEvent: historyEvent = new GenericEvent(eventId, GetPayloadText(reader)); break; case EventType.OrchestratorCompleted: historyEvent = new OrchestratorCompletedEvent(eventId); break; case EventType.OrchestratorStarted: historyEvent = new OrchestratorStartedEvent(eventId); break; case EventType.SubOrchestrationInstanceCompleted: historyEvent = new SubOrchestrationInstanceCompletedEvent(eventId, GetTaskId(reader), GetPayloadText(reader)); break; case EventType.SubOrchestrationInstanceCreated: historyEvent = new SubOrchestrationInstanceCreatedEvent(eventId) { Input = GetPayloadText(reader), InstanceId = null, // TODO Name = GetName(reader), Version = null, }; break; case EventType.SubOrchestrationInstanceFailed: historyEvent = new SubOrchestrationInstanceFailedEvent( eventId, taskScheduledId: GetTaskId(reader), reason: GetReason(reader), details: GetPayloadText(reader)); break; case EventType.TaskCompleted: historyEvent = new TaskCompletedEvent( eventId, taskScheduledId: GetTaskId(reader), result: GetPayloadText(reader)); break; case EventType.TaskFailed: historyEvent = new TaskFailedEvent( eventId, taskScheduledId: GetTaskId(reader), reason: GetReason(reader), details: GetPayloadText(reader)); break; case EventType.TaskScheduled: historyEvent = new TaskScheduledEvent(eventId) { Input = GetPayloadText(reader), Name = GetName(reader), Version = GetVersion(reader), }; break; case EventType.TimerCreated: historyEvent = new TimerCreatedEvent(eventId) { FireAt = GetVisibleTime(reader), }; break; case EventType.TimerFired: historyEvent = new TimerFiredEvent(eventId) { FireAt = GetVisibleTime(reader), TimerId = GetTaskId(reader), }; break; default: throw new InvalidOperationException($"Don't know how to interpret '{eventType}'."); } historyEvent.Timestamp = GetTimestamp(reader); historyEvent.IsPlayed = isOrchestrationHistory && (bool)reader["IsPlayed"]; return(historyEvent); }