public void CheckpointStarting(OrchestrationState state) { var logEvent = new LogEvents.CheckpointStartingEvent( state.Name, state.OrchestrationInstance, state.OrchestrationStatus); this.WriteLog(logEvent); }
public void CheckpointCompleted(OrchestrationState state, Stopwatch latencyStopwatch) { var logEvent = new LogEvents.CheckpointCompletedEvent( state.Name, state.OrchestrationInstance, latencyStopwatch.ElapsedMilliseconds); this.WriteLog(logEvent); }
/// <summary> /// Read an entity properties based on the supplied dictionary or entity properties /// </summary> /// <param name="properties">Dictionary of properties to read for the entity</param> /// <param name="operationContext">The operation context</param> public override void ReadEntity(IDictionary <string, EntityProperty> properties, OperationContext operationContext) { State = new OrchestrationState { OrchestrationInstance = new OrchestrationInstance { InstanceId = GetValue("InstanceId", properties, property => property.StringValue), ExecutionId = GetValue("ExecutionId", properties, property => property.StringValue) }, ParentInstance = new ParentInstance { Name = null, TaskScheduleId = -1, Version = null, OrchestrationInstance = new OrchestrationInstance { InstanceId = GetValue("ParentInstanceId", properties, property => property.StringValue), ExecutionId = GetValue("ParentExecutionId", properties, property => property.StringValue) } }, Name = GetValue("Name", properties, property => property.StringValue), Version = GetValue("Version", properties, property => property.StringValue), Status = GetValue("Status", properties, property => property.StringValue), Tags = GetTagsFromString(properties), CreatedTime = GetValue("CreatedTime", properties, property => property.DateTimeOffsetValue) .GetValueOrDefault() .DateTime, CompletedTime = GetValue("CompletedTime", properties, property => property.DateTimeOffsetValue) .GetValueOrDefault() .DateTime, LastUpdatedTime = GetValue("LastUpdatedTime", properties, property => property.DateTimeOffsetValue) .GetValueOrDefault() .DateTime, Size = GetValue("Size", properties, property => property.Int64Value).GetValueOrDefault(), CompressedSize = GetValue("CompressedSize", properties, property => property.Int64Value).GetValueOrDefault(), Input = GetValue("Input", properties, property => property.StringValue), Output = GetValue("Output", properties, property => property.StringValue) }; TaskTimeStamp = GetValue("TaskTimeStamp", properties, property => property.DateTimeOffsetValue) .GetValueOrDefault() .DateTime; string orchestrationStatusStr = GetValue("OrchestrationStatus", properties, property => property.StringValue); if (!Enum.TryParse(orchestrationStatusStr, out State.OrchestrationStatus)) { throw new InvalidOperationException("Invalid status string in state " + orchestrationStatusStr); } }
/// <inheritdoc /> public override async Task <OrchestrationState> GetStateAsync(string instanceId, string executionId) { if (instanceId == null) { throw new ArgumentNullException(nameof(instanceId)); } var stopwatch = new Stopwatch(); TableResult orchestration = await this.InstancesTable.ExecuteAsync(TableOperation.Retrieve <OrchestrationInstanceStatus>(instanceId, "")); stopwatch.Stop(); this.stats.StorageRequests.Increment(); this.stats.TableEntitiesRead.Increment(1); AnalyticsEventSource.Log.FetchedInstanceStatus( this.storageAccountName, this.taskHubName, instanceId, executionId ?? string.Empty, stopwatch.ElapsedMilliseconds); OrchestrationInstanceStatus orchestrationInstanceStatus = (OrchestrationInstanceStatus)orchestration.Result; if (orchestrationInstanceStatus == null) { return(null); } var orchestrationState = new OrchestrationState(); if (!Enum.TryParse(orchestrationInstanceStatus.RuntimeStatus, out orchestrationState.OrchestrationStatus)) { throw new ArgumentException($"{orchestrationInstanceStatus.RuntimeStatus} is not a valid OrchestrationStatus value."); } orchestrationState.OrchestrationInstance = new OrchestrationInstance { InstanceId = instanceId, ExecutionId = orchestrationInstanceStatus.ExecutionId, }; orchestrationState.Name = orchestrationInstanceStatus.Name; orchestrationState.Version = orchestrationInstanceStatus.Version; orchestrationState.Status = orchestrationInstanceStatus.CustomStatus; orchestrationState.CreatedTime = orchestrationInstanceStatus.CreatedTime; orchestrationState.LastUpdatedTime = orchestrationInstanceStatus.LastUpdatedTime; string[] results = await Task.WhenAll( this.GetOrchestrationInputAsync(orchestrationInstanceStatus), this.GetOrchestrationOutputAsync(orchestrationInstanceStatus)); orchestrationState.Input = results[0]; orchestrationState.Output = results[1]; return(orchestrationState); }
public async Task SimpleFanOutOrchestration_DurabilityTest() { int numToIterateTo = 500; var orchestrationService = TestHelpers.GetTestOrchestrationService(nameof(SimpleFanOutOrchestration_DurabilityTest)); var worker = new TaskHubWorker(orchestrationService); try { await worker.AddTaskOrchestrations(typeof(FanOutOrchestration)) .AddTaskActivities(typeof(SquareIntTask), typeof(SumIntTask)) .StartAsync(); var client = new TaskHubClient(orchestrationService); int[] numsToSum = new int[numToIterateTo]; for (int i = 0; i < numToIterateTo; i++) { numsToSum[i] = i + 1; } OrchestrationInstance id = await client.CreateOrchestrationInstanceAsync(typeof(FanOutOrchestration), numsToSum); try { await client.WaitForOrchestrationAsync(id, TimeSpan.FromMilliseconds(500), new CancellationToken()); } catch { //Timeout is expected in this case. 500 activities can't finish that fast. await worker.StopAsync(true); } // Resume orchestration on "new" client orchestrationService = TestHelpers.GetTestOrchestrationService(nameof(SimpleFanOutOrchestration_DurabilityTest)); worker = new TaskHubWorker(orchestrationService); await worker.AddTaskOrchestrations(typeof(FanOutOrchestration)) .AddTaskActivities(typeof(SquareIntTask), typeof(SumIntTask)) .StartAsync(); client = new TaskHubClient(orchestrationService); OrchestrationState result = await client.WaitForOrchestrationAsync(id, TimeSpan.FromSeconds(Debugger.IsAttached ? 20 : 20), new CancellationToken()); Assert.Equal(OrchestrationStatus.Completed, result.OrchestrationStatus); // Sum of square numbers 1 to n = n * (n+1) * (2n+1) / 6 int expectedResult = (numToIterateTo * (numToIterateTo + 1) * (2 * numToIterateTo + 1)) / 6; Assert.Equal(expectedResult, FanOutOrchestration.Result); } finally { await worker.StopAsync(true); await orchestrationService.DeleteAsync(); } }
public async Task TagsSubOrchestrationTest() { var c1 = new NameValueObjectCreator <TaskOrchestration>("ParentWorkflow", "V1", typeof(ParentWorkflow)); var c2 = new NameValueObjectCreator <TaskOrchestration>("ChildWorkflow", "V1", typeof(ChildWorkflow)); await taskHub.AddTaskOrchestrations(c1, c2) .StartAsync(); OrchestrationInstance instance = await client.CreateOrchestrationInstanceAsync( "ParentWorkflow", "V1", "TestInstance", true, new Dictionary <string, string>(2) { { ParentWorkflow.ParentTagName, ParentWorkflow.ParentTagValue }, { ParentWorkflow.SharedTagName, ParentWorkflow.ParentTagValue } }); OrchestrationState state = await client.WaitForOrchestrationAsync(instance, TimeSpan.FromMinutes(1), CancellationToken.None); bool isCompleted = (state?.OrchestrationStatus == OrchestrationStatus.Completed); Assert.IsTrue(isCompleted, TestHelpers.GetInstanceNotCompletedMessage(client, instance, 60)); Assert.AreEqual("Child completed.", ParentWorkflow.Result, "Orchestration Result is wrong!!!"); IDictionary <string, string> returnedTags = state.Tags; string returnedValue; // Check for parent tag untouched Assert.IsTrue(returnedTags.TryGetValue(ParentWorkflow.ParentTagName, out returnedValue)); Assert.AreEqual(ParentWorkflow.ParentTagValue, returnedValue); // Check for shared tag on parent with parent value Assert.IsTrue(returnedTags.TryGetValue(ParentWorkflow.SharedTagName, out returnedValue)); Assert.AreEqual(ParentWorkflow.ParentTagValue, returnedValue); // Get child state and check completion OrchestrationState childState = await client.GetOrchestrationStateAsync(ParentWorkflow.ChildWorkflowId); isCompleted = (childState?.OrchestrationStatus == OrchestrationStatus.Completed); Assert.IsTrue(isCompleted, TestHelpers.GetInstanceNotCompletedMessage(client, instance, 60)); returnedTags = childState.Tags; // Check for parent tag untouched Assert.IsTrue(returnedTags.TryGetValue(ParentWorkflow.ParentTagName, out returnedValue)); Assert.AreEqual(ParentWorkflow.ParentTagValue, returnedValue); // Check for shared tag on with child value Assert.IsTrue(returnedTags.TryGetValue(ParentWorkflow.SharedTagName, out returnedValue)); Assert.AreEqual(ParentWorkflow.ChildTagValue, returnedValue); // Check for child tag Assert.IsTrue(returnedTags.TryGetValue(ParentWorkflow.ChildTagName, out returnedValue)); Assert.AreEqual(ParentWorkflow.ChildTagValue, returnedValue); }
public async Task MockRaiseEventTest() { LocalOrchestrationService orchService = new LocalOrchestrationService(); TaskHubWorker worker = new TaskHubWorker(orchService); TaskHubClient client = new TaskHubClient(orchService); await worker.AddTaskOrchestrations(typeof(GenerationSignalOrchestration)) .StartAsync(); OrchestrationInstance id = await client.CreateOrchestrationInstanceAsync( typeof(GenerationSignalOrchestration), 5); var signalId = new OrchestrationInstance { InstanceId = id.InstanceId }; await Task.Delay(2 * 500); await client.RaiseEventAsync(signalId, "Count", "1"); GenerationSignalOrchestration.signal.Set(); await Task.Delay(2 * 500); GenerationSignalOrchestration.signal.Reset(); await client.RaiseEventAsync(signalId, "Count", "2"); await Task.Delay(2 * 500); await client.RaiseEventAsync(signalId, "Count", "3"); // will be recieved by next generation GenerationSignalOrchestration.signal.Set(); await Task.Delay(2 * 500); GenerationSignalOrchestration.signal.Reset(); await client.RaiseEventAsync(signalId, "Count", "4"); await Task.Delay(2 * 500); await client.RaiseEventAsync(signalId, "Count", "5"); // will be recieved by next generation await client.RaiseEventAsync(signalId, "Count", "6"); // lost await client.RaiseEventAsync(signalId, "Count", "7"); // lost GenerationSignalOrchestration.signal.Set(); OrchestrationState result = await client.WaitForOrchestrationAsync(new OrchestrationInstance { InstanceId = id.InstanceId }, TimeSpan.FromSeconds(40), CancellationToken.None); Assert.AreEqual(OrchestrationStatus.Completed, result.OrchestrationStatus); Assert.AreEqual("5", GenerationSignalOrchestration.Result, "Orchestration Result is wrong!!!"); }
/// <inheritdoc /> public override async Task <DurableOrchestrationStatus> GetStatusAsync(string instanceId, bool showHistory = false, bool showHistoryOutput = false) { OrchestrationState state = await this.client.GetOrchestrationStateAsync(instanceId); if (state == null) { return(null); } return(await this.GetDurableOrchestrationStatusAsync(state, showHistory, showHistoryOutput)); }
/// <inheritdoc /> public async Task <object> WriteEntitiesAsync(IEnumerable <InstanceEntityBase> entities) { using (var connection = await settings.GetDatabaseConnection()) using (var command = connection.CreateCommand()) { foreach (var entity in entities) { if (entity is OrchestrationStateInstanceEntity orchestration) { OrchestrationState state = orchestration.State; command.AddStatement(string.Format(MergeOrchestrationStateInstanceEntityQuery, settings.OrchestrationStateTableName), new { instanceId = state.OrchestrationInstance.InstanceId, executionId = state.OrchestrationInstance.ExecutionId, name = state.Name, version = state.Version, orchestrationStatus = state.OrchestrationStatus.ToString(), createdTime = state.CreatedTime, completedTime = state.CompletedTime, lastUpdatedTime = state.LastUpdatedTime, stateData = JsonDataConverter.Default.Serialize(state) }); } else if (entity is OrchestrationWorkItemInstanceEntity workItem) { command.AddStatement(string.Format(MergeOrchestrationWorkItemInstanceEntityQuery, settings.WorkItemTableName), new { instanceId = workItem.InstanceId, executionId = workItem.ExecutionId, sequenceNumber = workItem.SequenceNumber, eventTimestamp = workItem.EventTimestamp, historyEvent = JsonDataConverter.Default.Serialize(workItem.HistoryEvent) }); } else { throw new InvalidOperationException($"Invalid history event type: {entity.GetType()}"); } } if (command.CommandText.Any() == false) { return(null); } await connection.OpenAsync(); await command.ExecuteNonQueryAsync(); } return(null); }
private OrchestrationStateInstanceEntity tableStateToStateEvent(OrchestrationState state) { if (state == null) { return(null); } return(new OrchestrationStateInstanceEntity { State = state }); }
public async Task MultipleConcurrentRoleStartsTestNoInitialHub() { // Make sure we cleanup we start from scratch await this.taskHub.StopAsync(true); await this.taskHub.orchestrationService.DeleteAsync(); const int ConcurrentClientsAndHubs = 4; var rnd = new Random(); var clients = new List <TaskHubClient>(ConcurrentClientsAndHubs); var workers = new List <TaskHubWorker>(ConcurrentClientsAndHubs); IList <Task> tasks = new List <Task>(); for (var i = 0; i < ConcurrentClientsAndHubs; i++) { clients.Add(TestHelpers.CreateTaskHubClient()); workers.Add(TestHelpers.CreateTaskHub(new ServiceBusOrchestrationServiceSettings { TaskOrchestrationDispatcherSettings = { DispatcherCount = 4 }, TrackingDispatcherSettings = { DispatcherCount = 4 }, TaskActivityDispatcherSettings = { DispatcherCount = 4 } })); tasks.Add(workers[i].orchestrationService.CreateIfNotExistsAsync()); } await Task.WhenAll(tasks); GenerationBasicOrchestration.Result = 0; GenerationBasicTask.GenerationCount = 0; // ReSharper disable once UnusedVariable TaskHubWorker selectedHub = workers[(rnd.Next(ConcurrentClientsAndHubs))]; TaskHubClient selectedClient = clients[(rnd.Next(ConcurrentClientsAndHubs))]; tasks.Clear(); for (var i = 0; i < ConcurrentClientsAndHubs; i++) { tasks.Add(workers[i].AddTaskOrchestrations(typeof(GenerationBasicOrchestration)) .AddTaskActivities(new GenerationBasicTask()) .StartAsync()); } await Task.WhenAll(tasks); OrchestrationInstance instance = await selectedClient.CreateOrchestrationInstanceAsync(typeof(GenerationBasicOrchestration), 4); OrchestrationState state = await selectedClient.WaitForOrchestrationAsync(instance, TimeSpan.FromSeconds(60), CancellationToken.None); Assert.IsNotNull(state); Assert.AreEqual(OrchestrationStatus.Completed, state.OrchestrationStatus, TestHelpers.GetInstanceNotCompletedMessage(this.client, instance, 60)); Assert.AreEqual(4, GenerationBasicOrchestration.Result, "Orchestration Result is wrong!!!"); await Task.WhenAll(workers.Select(worker => worker.StopAsync(true))); }
internal bool Matches(OrchestrationState targetState) { if (targetState == null) { throw new ArgumentNullException(nameof(targetState)); } return((!this.HasRuntimeStatus || this.RuntimeStatus.Contains(targetState.OrchestrationStatus)) && (string.IsNullOrWhiteSpace(this.InstanceIdPrefix) || targetState.OrchestrationInstance.InstanceId.StartsWith(this.InstanceIdPrefix)) && (!this.CreatedTimeFrom.HasValue || targetState.CreatedTime >= this.CreatedTimeFrom.Value) && (!this.CreatedTimeTo.HasValue || targetState.CreatedTime <= this.CreatedTimeTo.Value)); }
public void Process(PurgeBatchIssued purgeBatchIssued, EffectTracker effects) { OrchestrationState state = this.OrchestrationState; if (this.OrchestrationState != null && purgeBatchIssued.InstanceQuery.Matches(this.OrchestrationState)) { this.OrchestrationState = null; purgeBatchIssued.Purged.Add(this.InstanceId); effects.Add(TrackedObjectKey.History(this.InstanceId)); } }
public async Task NonDeterministicOrchestrationTest() { await this.taskHub.AddTaskOrchestrations(typeof(NonDeterministicOrchestration)) .AddTaskActivities(typeof(FirstTask)) .StartAsync(); this.taskHub.TaskActivityDispatcher.IncludeDetails = true; OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NonDeterministicOrchestration), "FAILTIMER"); bool isCompleted = await TestHelpers.WaitForInstanceAsync(this.client, instance, 60); Utils.UnusedParameter(isCompleted); OrchestrationState state = await this.client.GetOrchestrationStateAsync(instance); Assert.AreEqual(OrchestrationStatus.Failed, state.OrchestrationStatus); Assert.IsTrue(state.Output.Contains("TimerCreatedEvent")); instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NonDeterministicOrchestration), "FAILTASK"); isCompleted = await TestHelpers.WaitForInstanceAsync(this.client, instance, 60); Utils.UnusedParameter(isCompleted); state = await this.client.GetOrchestrationStateAsync(instance); Assert.AreEqual(OrchestrationStatus.Failed, state.OrchestrationStatus); Assert.IsTrue(state.Output.Contains("TaskScheduledEvent")); instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NonDeterministicOrchestration), "FAILSUBORCH"); isCompleted = await TestHelpers.WaitForInstanceAsync(this.client, instance, 60); Utils.UnusedParameter(isCompleted); state = await this.client.GetOrchestrationStateAsync(instance); Assert.AreEqual(OrchestrationStatus.Failed, state.OrchestrationStatus); Assert.IsTrue(state.Output.Contains("SubOrchestrationInstanceCreatedEvent")); instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NonDeterministicOrchestration), "PARENTORCH"); isCompleted = await TestHelpers.WaitForInstanceAsync(this.client, instance, 60); Utils.UnusedParameter(isCompleted); state = await this.client.GetOrchestrationStateAsync(instance); Assert.AreEqual(OrchestrationStatus.Completed, state.OrchestrationStatus); Assert.IsTrue(state.Output.Contains("Non-Deterministic workflow detected")); }
/// <summary> /// Terminates a running orchestration instance. /// </summary> /// <param name="instanceId">The ID of the orchestration instance to terminate.</param> /// <param name="reason">The reason for terminating the orchestration instance.</param> /// <returns>A task that completes when the terminate message is enqueued.</returns> public async Task TerminateAsync(string instanceId, string reason) { OrchestrationState state = await this.GetOrchestrationInstanceAsync(instanceId); if (state.OrchestrationStatus == OrchestrationStatus.Running || state.OrchestrationStatus == OrchestrationStatus.Pending || state.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew) { await this.client.TerminateInstanceAsync(state.OrchestrationInstance, reason); this.traceHelper.FunctionTerminated(this.hubName, state.Name, state.Version, instanceId, reason); } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { OrchestrationInstance instance = await _client.CreateOrchestrationInstanceAsync( typeof(GreetingsOrchestration), _instanceId, null); OrchestrationState result = await _client.WaitForOrchestrationAsync( instance, TimeSpan.FromSeconds(60)); _console.WriteLine(); _console.WriteLine($"Orchestration finished."); _console.WriteLine($"Run stats: {result.Status}"); _console.WriteLine("Press Ctrl+C to exit"); }
/// <inheritdoc /> async Task IDurableOrchestrationClient.RewindAsync(string instanceId, string reason) { OrchestrationState state = await this.GetOrchestrationInstanceStateAsync(instanceId); if (state.OrchestrationStatus != OrchestrationStatus.Failed) { throw new InvalidOperationException("The rewind operation is only supported on failed orchestration instances."); } await this.DurabilityProvider.RewindAsync(instanceId, reason); this.traceHelper.FunctionRewound(this.TaskHubName, state.Name, instanceId, reason); }
public async Task SingleActivity() { string input = $"[{DateTime.UtcNow:o}]"; TestInstance <string> instance = await this.testService.RunOrchestration( input, orchestrationName : "OrchestrationWithActivity", implementation : (ctx, input) => ctx.ScheduleTask <string>("SayHello", "", input), activities : ("SayHello", TestService.MakeActivity((TaskContext ctx, string input) => $"Hello, {input}!"))); OrchestrationState state = await instance.WaitForCompletion( expectedOutput : $"Hello, {input}!"); }
async Task SessionExceededLimitSubTestWithInputSize(int inputSize) { string input = TestUtils.GenerateRandomString(inputSize); OrchestrationInstance id = await client.CreateOrchestrationInstanceAsync(typeof(LargeSessionOrchestration), new Tuple <string, int>(input, 2)); bool isCompleted = await TestHelpers.WaitForInstanceAsync(client, id, 60, true); await Task.Delay(20000); OrchestrationState state = await client.GetOrchestrationStateAsync(id); Assert.AreEqual(OrchestrationStatus.Completed, state.OrchestrationStatus); Assert.AreEqual($"0:{input}-1:{input}-", LargeSessionOrchestration.Result); }
public async Task CatchInvalidOperationException(ErrorPropagationMode mode) { // The error propagation mode must be set before the worker is started this.worker.ErrorPropagationMode = mode; await this.worker .AddTaskOrchestrations(typeof(ExceptionHandlingOrchestration)) .AddTaskActivities(typeof(ThrowInvalidOperationException)) .StartAsync(); // This is required for exceptions to be serialized this.worker.TaskActivityDispatcher.IncludeDetails = true; OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(ExceptionHandlingOrchestration), null); OrchestrationState state = await this.client.WaitForOrchestrationAsync(instance, DefaultTimeout); Assert.IsNotNull(state); Assert.AreEqual(OrchestrationStatus.Completed, state.OrchestrationStatus); Assert.IsNotNull(state.Output, "The expected error information wasn't found!"); if (mode == ErrorPropagationMode.SerializeExceptions) { // The exception should be deserializable InvalidOperationException e = JsonConvert.DeserializeObject <InvalidOperationException>(state.Output); Assert.IsNotNull(e); Assert.AreEqual("This is a test exception", e.Message); } else if (mode == ErrorPropagationMode.UseFailureDetails) { // The failure details should contain the relevant exception metadata FailureDetails details = JsonConvert.DeserializeObject <FailureDetails>(state.Output); Assert.IsNotNull(details); Assert.AreEqual(typeof(InvalidOperationException).FullName, details.ErrorType); Assert.IsTrue(details.IsCausedBy <InvalidOperationException>()); Assert.IsTrue(details.IsCausedBy <Exception>()); // check that base types work too Assert.AreEqual("This is a test exception", details.ErrorMessage); Assert.IsNotNull(details.StackTrace); // The callstack should be in the error details string expectedCallstackSubstring = typeof(ThrowInvalidOperationException).FullName !.Replace('+', '.'); Assert.IsTrue( details.StackTrace !.IndexOf(expectedCallstackSubstring) > 0, $"Expected to find {expectedCallstackSubstring} in the exception details. Actual: {details.StackTrace}"); } else { Assert.Fail($"Unexpected {nameof(ErrorPropagationMode)} value: {mode}"); } }
/// <inheritdoc /> public override async Task RewindAsync(string instanceId, string reason) { OrchestrationState state = await this.GetOrchestrationInstanceAsync(instanceId); if (state.OrchestrationStatus != OrchestrationStatus.Failed) { throw new InvalidOperationException("The rewind operation is only supported on failed orchestration instances."); } var service = (AzureStorageOrchestrationService)this.client.ServiceClient; await service.RewindTaskOrchestrationAsync(instanceId, reason); this.traceHelper.FunctionRewound(this.hubName, state.Name, instanceId, reason); }
/// <inheritdoc/> public async override Task <string> RetrieveSerializedEntityState(EntityId entityId, JsonSerializerSettings serializerSettings) { var instanceId = ProviderUtils.GetSchedulerIdFromEntityId(entityId); OrchestrationState state = await this.Service.GetOrchestrationStateAsync(instanceId, true, true); if (ProviderUtils.TryGetEntityStateFromSerializedSchedulerState(state, serializerSettings, out string result)) { return(result); } else { return(null); } }
/// <summary> /// Queries the database for all orchestration instances that match a given filter. /// </summary> /// <param name="query">The query parameters to use as a filter.</param> /// <param name="cancellationToken">A token for cancelling the query.</param> /// <returns>Returns a collection of <see cref="OrchestrationState"/> objects for orchestrations that match the specified query filter.</returns> public async Task <IReadOnlyCollection <OrchestrationState> > GetManyOrchestrationsAsync(SqlOrchestrationQuery query, CancellationToken cancellationToken) { if (query.PageSize < 1) { throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(query.PageSize)} must be a positive number."); } if (query.PageNumber < 0 || query.PageNumber > short.MaxValue) { throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(query.PageNumber)} must be between 0 and {short.MaxValue} (inclusive)."); } SqlDateTime createdTimeFrom = query.CreatedTimeFrom.ToSqlUtcDateTime(SqlDateTime.MinValue); SqlDateTime createdTimeTo = query.CreatedTimeTo.ToSqlUtcDateTime(SqlDateTime.MaxValue); using SqlConnection connection = await this.GetAndOpenConnectionAsync(cancellationToken); using SqlCommand command = this.GetSprocCommand(connection, "dt._QueryManyOrchestrations"); command.Parameters.Add("@PageSize", SqlDbType.SmallInt).Value = query.PageSize; command.Parameters.Add("@PageNumber", SqlDbType.SmallInt).Value = query.PageNumber; command.Parameters.Add("@FetchInput", SqlDbType.Bit).Value = query.FetchInput; command.Parameters.Add("@FetchOutput", SqlDbType.Bit).Value = query.FetchOutput; command.Parameters.Add("@CreatedTimeFrom", SqlDbType.DateTime).Value = createdTimeFrom; command.Parameters.Add("@CreatedTimeTo", SqlDbType.DateTime).Value = createdTimeTo; command.Parameters.Add("@InstanceIDPrefix", SqlDbType.VarChar, size: 100).Value = query.InstanceIdPrefix ?? SqlString.Null; if (query.StatusFilter?.Count > 0) { string filter = string.Join(",", query.StatusFilter); command.Parameters.Add("@RuntimeStatusFilter", SqlDbType.VarChar, size: 200).Value = filter; } using DbDataReader reader = await SqlUtils.ExecuteReaderAsync( command, this.traceHelper, instanceId : null, cancellationToken); var results = new List <OrchestrationState>(query.PageSize); while (await reader.ReadAsync(cancellationToken)) { OrchestrationState state = reader.GetOrchestrationState(); results.Add(state); } return(results); }
internal static DurableOrchestrationStatus ConvertOrchestrationStateToStatus(OrchestrationState orchestrationState, JArray historyArray = null) { return(new DurableOrchestrationStatus { Name = orchestrationState.Name, InstanceId = orchestrationState.OrchestrationInstance.InstanceId, CreatedTime = orchestrationState.CreatedTime, LastUpdatedTime = orchestrationState.LastUpdatedTime, RuntimeStatus = (OrchestrationRuntimeStatus)orchestrationState.OrchestrationStatus, CustomStatus = ParseToJToken(orchestrationState.Status), Input = ParseToJToken(orchestrationState.Input), Output = ParseToJToken(orchestrationState.Output), History = historyArray, }); }
/// <inheritdoc /> public override async Task <DurableOrchestrationStatus> GetStatusAsync(string instanceId, bool showHistory = false, bool showHistoryOutput = false, bool showInput = true) { // TODO this cast is to avoid to change DurableTask.Core. Change it to use TaskHubClient. var storageService = (AzureStorageOrchestrationService)this.client.ServiceClient; IList <OrchestrationState> stateList = await storageService.GetOrchestrationStateAsync(instanceId, allExecutions : false, fetchInput : showInput); OrchestrationState state = stateList?.FirstOrDefault(); if (state == null || state.OrchestrationInstance == null) { return(null); } return(await this.GetDurableOrchestrationStatusAsync(state, showHistory, showHistoryOutput)); }
public WorkflowResult(OrchestrationState ctx) { OrchestrationStatus = ctx.OrchestrationStatus; switch (OrchestrationStatus) { case OrchestrationStatus.Completed: Result = JsonConvert.DeserializeObject <T>(ctx.Output); break; case OrchestrationStatus.Failed: Error = ctx.Output; break; } Status = ctx.Status; }
public async Task CheckpointOrchestrationFault() { // This test needs to wait for the lock timeout to expire after the injected fault // before it will retry the checkpoint. this.testService.OrchestrationServiceOptions.WorkItemLockTimeout = TimeSpan.FromSeconds(5); // Set up a mock that will fail the first call, but succeed the second call bool faultedOnce = false; this.testService.OrchestrationServiceMock.Setup( svc => svc.CompleteTaskOrchestrationWorkItemAsync( It.IsAny <TaskOrchestrationWorkItem>(), It.IsAny <OrchestrationRuntimeState>(), It.IsAny <IList <TaskMessage> >(), It.IsAny <IList <TaskMessage> >(), It.IsAny <IList <TaskMessage> >(), It.IsAny <TaskMessage>(), It.IsAny <OrchestrationState>())) .Callback(() => { if (!faultedOnce) { faultedOnce = true; throw new Exception("Kah-BOOOOM!!!"); } }); // Does nothing except return the original input TestInstance <string> instance = await this.testService.RunOrchestration( input : "Hello, world!", orchestrationName : "EmptyOrchestration", implementation : (ctx, input) => Task.FromResult(input)); OrchestrationState state = await instance.WaitForCompletion(); Assert.Equal(OrchestrationStatus.Completed, state.OrchestrationStatus); Assert.True(faultedOnce); // Verify that the CompleteTaskOrchestrationWorkItemAsync method was called exactly twice this.testService.OrchestrationServiceMock.Verify(svc => svc.CompleteTaskOrchestrationWorkItemAsync( It.IsAny <TaskOrchestrationWorkItem>(), It.IsAny <OrchestrationRuntimeState>(), It.IsAny <IList <TaskMessage> >(), It.IsAny <IList <TaskMessage> >(), It.IsAny <IList <TaskMessage> >(), It.IsAny <TaskMessage>(), It.IsAny <OrchestrationState>()), Times.Exactly(2)); }
/// <inheritdoc /> public Task CreateTaskOrchestrationAsync(TaskMessage creationMessage, OrchestrationStatus[] dedupeStatuses) { ExecutionStartedEvent ee = creationMessage.Event as ExecutionStartedEvent; if (ee == null) { throw new InvalidOperationException("Invalid creation task message"); } lock (this.thisLock) { Dictionary <string, OrchestrationState> ed; if (!this.instanceStore.TryGetValue(creationMessage.OrchestrationInstance.InstanceId, out ed)) { ed = new Dictionary <string, OrchestrationState>(); this.instanceStore[creationMessage.OrchestrationInstance.InstanceId] = ed; } var latestState = ed.Values.OrderBy(state => state.CreatedTime).FirstOrDefault(state => state.OrchestrationStatus != OrchestrationStatus.ContinuedAsNew); if (latestState != null && (dedupeStatuses == null || dedupeStatuses.Contains(latestState.OrchestrationStatus))) { // An orchestration with same instance id is already running throw new OrchestrationAlreadyExistsException($"An orchestration with id '{creationMessage.OrchestrationInstance.InstanceId}' already exists. It is in state {latestState.OrchestrationStatus}"); } OrchestrationState newState = new OrchestrationState() { OrchestrationInstance = new OrchestrationInstance { InstanceId = creationMessage.OrchestrationInstance.InstanceId, ExecutionId = creationMessage.OrchestrationInstance.ExecutionId, }, CreatedTime = DateTime.UtcNow, OrchestrationStatus = OrchestrationStatus.Pending, Version = ee.Version, Name = ee.Name, Input = ee.Input, }; ed.Add(creationMessage.OrchestrationInstance.ExecutionId, newState); this.orchestratorQueue.SendMessage(creationMessage); } return(Task.FromResult <object>(null)); }
public void SessionNotExceededLimitTest() { taskHub.AddTaskOrchestrations(typeof(LargeSessionOrchestration)) .AddTaskActivities(typeof(LargeSessionTaskActivity)) .Start(); OrchestrationInstance id = client.CreateOrchestrationInstance(typeof(LargeSessionOrchestration), 15); bool isCompleted = TestHelpers.WaitForInstance(client, id, 90, true); Thread.Sleep(20000); OrchestrationState state = client.GetOrchestrationState(id); Assert.AreEqual(OrchestrationStatus.Completed, state.OrchestrationStatus); }
private async Task <OrchestrationState> GetOrchestrationInstanceAsync(string instanceId) { if (string.IsNullOrEmpty(instanceId)) { throw new ArgumentNullException(nameof(instanceId)); } OrchestrationState state = await this.client.GetOrchestrationStateAsync(instanceId); if (state == null || state.OrchestrationInstance == null) { throw new ArgumentException($"No instance with ID '{instanceId}' was found.", nameof(instanceId)); } return(state); }