Exemplo n.º 1
0
        public void CheckpointStarting(OrchestrationState state)
        {
            var logEvent = new LogEvents.CheckpointStartingEvent(
                state.Name,
                state.OrchestrationInstance,
                state.OrchestrationStatus);

            this.WriteLog(logEvent);
        }
Exemplo n.º 2
0
        public void CheckpointCompleted(OrchestrationState state, Stopwatch latencyStopwatch)
        {
            var logEvent = new LogEvents.CheckpointCompletedEvent(
                state.Name,
                state.OrchestrationInstance,
                latencyStopwatch.ElapsedMilliseconds);

            this.WriteLog(logEvent);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 5
0
        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();
            }
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        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));
        }
Exemplo n.º 9
0
        /// <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
            });
        }
Exemplo n.º 11
0
        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)));
        }
Exemplo n.º 12
0
        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));
        }
Exemplo n.º 13
0
        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));
            }
        }
Exemplo n.º 14
0
        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);
            }
        }
Exemplo n.º 16
0
            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);
        }
Exemplo n.º 18
0
        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}!");
        }
Exemplo n.º 19
0
        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}");
            }
        }
Exemplo n.º 21
0
        /// <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,
     });
 }
Exemplo n.º 25
0
        /// <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;
        }
Exemplo n.º 27
0
        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));
        }
Exemplo n.º 29
0
        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);
        }