Esempio n. 1
0
        // Intentionally NOT using async/await here, because we need yield return.
        // The magic is to only load all the pages, when it is really needed (e.g. when sorting is used).
        private static IEnumerable <DurableOrchestrationStatus> ListAllInstances(this IDurableClient durableClient, DateTime?timeFrom, DateTime?timeTill, bool showInput)
        {
            var queryCondition = new OrchestrationStatusQueryCondition()
            {
                PageSize  = ListInstancesPageSize,
                ShowInput = showInput
            };

            if (timeFrom.HasValue)
            {
                queryCondition.CreatedTimeFrom = timeFrom.Value;
            }
            if (timeTill.HasValue)
            {
                queryCondition.CreatedTimeTo = timeTill.Value;
            }

            OrchestrationStatusQueryResult response = null;

            do
            {
                queryCondition.ContinuationToken = response == null ? null : response.ContinuationToken;

                response = durableClient.ListInstancesAsync(queryCondition, CancellationToken.None).Result;
                foreach (var item in response.DurableOrchestrationState)
                {
                    yield return(item);
                }
            }while (!string.IsNullOrEmpty(response.ContinuationToken));
        }
Esempio n. 2
0
        //public const int MonitorTimeoutHours = 1;
        public static async Task <DurableOrchestrationStatus> FindJob <T>(
            this IDurableClient client,
            DateTime time,
            string workflowName,
            T creditOperation,
            bool runningOnly  = true,
            bool confirmation = true)
        {
            var filter = runningOnly ?
                         new List <OrchestrationRuntimeStatus> {
                OrchestrationRuntimeStatus.Running
            }
                : new List <OrchestrationRuntimeStatus>();
            var offset = TimeSpan.FromMinutes(confirmation ?
                                              ExpirationMinutes : DefaultSpanMinutes);

            var condition = new OrchestrationStatusQueryCondition()
            {
                RuntimeStatus   = filter,
                CreatedTimeFrom = time.Subtract(offset),
                CreatedTimeTo   = time.Add(offset)
            };

            var instances = await client.ListInstancesAsync(condition, new System.Threading.CancellationToken());

            foreach (var instance in instances.DurableOrchestrationState)
            {
                if (instance.Input.ToObject <T>().Equals(creditOperation) &&
                    instance.Name == workflowName)
                {
                    return(instance);
                }
            }
            return(null);
        }
Esempio n. 3
0
        public void Parse_OrchestrationStatusQueryCondition()
        {
            var runtimeStatus = new List <OrchestrationRuntimeStatus>()
            {
                OrchestrationRuntimeStatus.Failed,
                OrchestrationRuntimeStatus.Terminated,
            };
            var createdTimeFrom = new DateTime(2019, 1, 3);
            var createdTimeTo   = new DateTime(2019, 1, 4);
            var taskHubNames    = new List <string>()
            {
                "baz",
                "qux",
            };

            var condition = new OrchestrationStatusQueryCondition
            {
                RuntimeStatus   = runtimeStatus,
                CreatedTimeFrom = createdTimeFrom,
                CreatedTimeTo   = createdTimeTo,
                TaskHubNames    = taskHubNames,
            };

            var result = AzureStorageDurabilityProvider.ConvertWebjobsDurableConditionToAzureStorageCondition(condition);

            Assert.Equal(OrchestrationStatus.Failed, result.RuntimeStatus.First());
            Assert.Equal(OrchestrationStatus.Terminated, result.RuntimeStatus.Last());
            Assert.Equal(createdTimeFrom, result.CreatedTimeFrom);
            Assert.Equal(createdTimeTo, result.CreatedTimeTo);
            Assert.Equal(taskHubNames, result.TaskHubNames);
        }
Esempio n. 4
0
 public Task <OrchestrationStatusQueryResult> ListInstancesAsync(OrchestrationStatusQueryCondition condition, CancellationToken cancellationToken)
 {
     return(Task.FromResult(new OrchestrationStatusQueryResult
     {
         DurableOrchestrationState = _instances.Select(ToStatusObject).ToArray()
     }));
 }
Esempio n. 5
0
        public virtual async Task <string> runAction(IDurableOrchestrationClient starter, ILogger log)
        {
            var entLookup = Environment.GetEnvironmentVariable("LCU-ENTERPRISE-LOOKUP");

            try
            {
                var listInstanceQuery = new OrchestrationStatusQueryCondition()
                {
                    PageSize      = 1000,
                    RuntimeStatus = new[] { OrchestrationRuntimeStatus.Running, OrchestrationRuntimeStatus.Pending }
                };

                var instances = await starter.ListInstancesAsync(listInstanceQuery, new System.Threading.CancellationToken());

                var running = new HashSet <string>(instances.DurableOrchestrationState.Select(instance => instance.InstanceId));

                var terminateTasks = running.Select(instanceId =>
                {
                    return(starter.TerminateAsync(instanceId, "Cleanup"));
                });

                await Task.WhenAll(terminateTasks);

                while (running.Count > 0)
                {
                    var results = await Task.WhenAll(instances.DurableOrchestrationState.Select(instance => starter.GetStatusAsync(instance.InstanceId)));

                    foreach (var status in results)
                    {
                        // Remove any terminated or completed instances from the hashset
                        if (status != null &&
                            status.RuntimeStatus != OrchestrationRuntimeStatus.Pending &&
                            status.RuntimeStatus != OrchestrationRuntimeStatus.Running)
                        {
                            running.Remove(status.InstanceId);
                        }
                    }

                    await Task.Delay(TimeSpan.FromMilliseconds(1000));
                }

                var instanceId = await starter.StartAction("RenewCertificatesOrchestration", new StateDetails()
                {
                    EnterpriseLookup = entLookup
                }, new ExecuteActionRequest()
                {
                    Arguments = new
                    {
                        EnterpriseLookup = entLookup
                    }.JSONConvert <MetadataModel>()
                }, log);

                return(instanceId);
            }
            catch (Exception ex)
            {
                return(null);
            }
        }
        public static async Task<IActionResult> PurgeCities(
           [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "purgecities")] HttpRequest req,
           [DurableClient] IDurableClient client,
           ILogger log)
        {
            var queryCondition = new OrchestrationStatusQueryCondition()
            {
                InstanceIdPrefix = "Orch",
            };

            PurgeHistoryResult result = await client.PurgeInstanceHistoryAsync(default,default,default);
        public async Task Run(
            [TimerTrigger(PurgeFrequencyVariable)] TimerInfo myTimer,
            [DurableClient] IDurableOrchestrationClient client,
            ILogger log,
            CancellationToken hostCancellationToken)
        {
            EnsureArg.IsNotNull(client, nameof(client));
            EnsureArg.IsNotNull(myTimer, nameof(myTimer));
            EnsureArg.IsNotNull(log, nameof(log));

            var orchestrationInstanceIdList = new List <string>();

            log.LogInformation("Purging orchestration instance history at: {Timestamp}", _getUtcNow());
            if (myTimer.IsPastDue)
            {
                log.LogWarning("Current function invocation is later than scheduled.");
            }

            // Specify conditions for orchestration instances.
            var condition = new OrchestrationStatusQueryCondition
            {
                RuntimeStatus     = _purgeConfig.RuntimeStatuses,
                CreatedTimeFrom   = DateTime.MinValue,
                CreatedTimeTo     = _getUtcNow().AddDays(-_purgeConfig.MinimumAgeDays),
                ContinuationToken = null
            };

            do
            {
                OrchestrationStatusQueryResult listOfOrchestrators =
                    await client.ListInstancesAsync(condition, hostCancellationToken);

                condition.ContinuationToken = listOfOrchestrators.ContinuationToken;

                // Loop through the orchestration instances and purge them.
                foreach (DurableOrchestrationStatus orchestration in listOfOrchestrators.DurableOrchestrationState)
                {
                    orchestrationInstanceIdList.Add(orchestration.InstanceId);
                    await client.PurgeInstanceHistoryAsync(orchestration.InstanceId);
                }
            } while (condition.ContinuationToken != null);

            if (orchestrationInstanceIdList.Count != 0)
            {
                log.LogInformation("{Count} Durable Functions cleaned up successfully.", orchestrationInstanceIdList.Count);
                log.LogDebug("List of cleaned instance IDs: {list}", string.Join(", ", orchestrationInstanceIdList));
            }
            else
            {
                log.LogInformation("No Orchestration instances found within given conditions.");
            }
        }
Esempio n. 8
0
        public static async Task GetAllStatuses(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient client,
            ILogger log)
        {
            var noFilter = new OrchestrationStatusQueryCondition();
            var result   = await client.ListInstancesAsync(
                noFilter,
                CancellationToken.None);

            foreach (var instance in result.DurableOrchestrationState)
            {
                log.LogInformation(JsonConvert.SerializeObject(instance));
            }
        }
Esempio n. 9
0
        public static async Task AF_WAITINGFORAPPROVAL(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "raiseEvent/{instanceId}")] HttpRequest req, string instanceId, [DurableClient] IDurableOrchestrationClient client,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var noFilter = new OrchestrationStatusQueryCondition();
            OrchestrationStatusQueryResult result = await client.ListInstancesAsync(
                noFilter,
                CancellationToken.None);

            foreach (DurableOrchestrationStatus instance in result.DurableOrchestrationState)
            {
                log.LogInformation(JsonConvert.SerializeObject(instance));
            }

            await client.RaiseEventAsync(instanceId, "WaitingForApproval", true);
        }
Esempio n. 10
0
        public static async Task <IActionResult> AF_GETINSTANCES(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "instances/{instanceId}")] HttpRequest req, string instanceId, [DurableClient] IDurableOrchestrationClient client,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var noFilter = new OrchestrationStatusQueryCondition();
            OrchestrationStatusQueryResult result = await client.ListInstancesAsync(
                noFilter,
                CancellationToken.None);

            foreach (DurableOrchestrationStatus instance in result.DurableOrchestrationState)
            {
                log.LogInformation(JsonConvert.SerializeObject(instance.InstanceId));
            }

            return(new OkObjectResult(result.DurableOrchestrationState));
        }
Esempio n. 11
0
        // Intentionally NOT using async/await here, because we need yield return.
        // The magic is to only load all the pages, when it is really needed (e.g. when sorting is used).
        private static IEnumerable <DurableOrchestrationStatus> ListAllInstances(this IDurableClient durableClient, DateTime?timeFrom, DateTime?timeTill, bool showInput, string[] statuses)
        {
            var queryCondition = new OrchestrationStatusQueryCondition()
            {
                PageSize  = ListInstancesPageSize,
                ShowInput = showInput
            };

            if (timeFrom.HasValue)
            {
                queryCondition.CreatedTimeFrom = timeFrom.Value;
            }
            if (timeTill.HasValue)
            {
                queryCondition.CreatedTimeTo = timeTill.Value;
            }

            if (statuses != null)
            {
                var runtimeStatuses = statuses.ToRuntimeStatuses().ToList();

                // Durable Entities are always 'Running'
                if (statuses.Contains(DurableEntityRuntimeStatus, StringComparer.OrdinalIgnoreCase))
                {
                    runtimeStatuses.Add(OrchestrationRuntimeStatus.Running);
                }

                queryCondition.RuntimeStatus = runtimeStatuses;
            }

            OrchestrationStatusQueryResult response = null;

            do
            {
                queryCondition.ContinuationToken = response == null ? null : response.ContinuationToken;

                response = durableClient.ListInstancesAsync(queryCondition, CancellationToken.None).Result;
                foreach (var item in response.DurableOrchestrationState)
                {
                    yield return(item);
                }
            }while (!string.IsNullOrEmpty(response.ContinuationToken));
        }
        public static async Task<IActionResult> CountCities(
           [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "countcities")] HttpRequest req,
           [DurableClient] IDurableClient client,
           ILogger log)
        {
            var queryCondition = new OrchestrationStatusQueryCondition()
            {
                InstanceIdPrefix = "Orch",
            };

            int completed = 0;
            int pending = 0;
            int running = 0;
            int other = 0;

            do
            {
                OrchestrationStatusQueryResult result = await client.ListInstancesAsync(queryCondition, CancellationToken.None);
                queryCondition.ContinuationToken = result.ContinuationToken;

                foreach (var status in result.DurableOrchestrationState)
                {
                    if (status.RuntimeStatus == OrchestrationRuntimeStatus.Pending)
                    {
                        pending++;
                    }
                    else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Running)
                    {
                        running++;
                    }
                    else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
                    {
                        completed++;
                    }
                    else
                    {
                        other++;
                    }
                }
            } while (queryCondition.ContinuationToken != null);

            return new OkObjectResult($"{pending+running+completed+other} orchestration instances ({pending} pending, {running} running, {completed} completed, {other} other)\n");
        }
        public static async Task <HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            OrchestrationStatusQueryCondition status = new OrchestrationStatusQueryCondition();

            List <Microsoft.Azure.WebJobs.Extensions.DurableTask.OrchestrationRuntimeStatus> sL = new List <Microsoft.Azure.WebJobs.Extensions.DurableTask.OrchestrationRuntimeStatus>();

            sL.Add(OrchestrationRuntimeStatus.Running);
            sL.Add(OrchestrationRuntimeStatus.Completed);
            status.RuntimeStatus = sL;


            string instanceId;

            // Function input comes from the request content.
            if (string.IsNullOrEmpty(_testMessage))
            {
                instanceId = await starter.StartNewAsync("DurableFunctionsOrchestrationTicTacToe", null);

                _testMessage = instanceId;
            }
            else
            {
                instanceId = await starter.StartNewAsync <string>("DurableFunctionsOrchestrationTicTacToe", _testMessage, null);
            }


            var openInstances = await starter.GetStatusAsync(instanceId, true, false, false);

            log.LogInformation($"This is number of running instances:  '{openInstances.RuntimeStatus}'");
            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
            log.LogInformation($"Test Mesage = '{_testMessage}'.");

            return(starter.CreateCheckStatusResponse(req, instanceId));
        }
Esempio n. 14
0
 public Task <OrchestrationStatusQueryResult> GetStatusAsync(OrchestrationStatusQueryCondition condition, CancellationToken cancellationToken)
 {
     return(this.innerClient.GetStatusAsync(condition, cancellationToken));
 }
Esempio n. 15
0
 public Task <OrchestrationStatusQueryResult> GetStatusAsync(OrchestrationStatusQueryCondition condition, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
Esempio n. 16
0
        public override async Task <OrchestrationStatusQueryResult> GetOrchestrationStateWithPagination(OrchestrationStatusQueryCondition condition, CancellationToken cancellationToken)
        {
            if (condition == null)
            {
                throw new ArgumentNullException(nameof(condition));
            }

            var query = new SqlOrchestrationQuery
            {
                PageSize         = condition.PageSize,
                FetchInput       = condition.ShowInput,
                CreatedTimeFrom  = condition.CreatedTimeFrom,
                CreatedTimeTo    = condition.CreatedTimeTo,
                InstanceIdPrefix = condition.InstanceIdPrefix,
            };

            if (condition.RuntimeStatus?.Any() == true)
            {
                query.StatusFilter = new HashSet <OrchestrationStatus>(condition.RuntimeStatus.Select(status => (OrchestrationStatus)status));
            }

            // The continuation token is just a page number.
            if (string.IsNullOrWhiteSpace(condition.ContinuationToken))
            {
                query.PageNumber = 0;
            }
            else if (int.TryParse(condition.ContinuationToken, out int pageNumber))
            {
                query.PageNumber = pageNumber;
            }
            else
            {
                throw new ArgumentException($"The continuation token '{condition.ContinuationToken}' is invalid.", nameof(condition));
            }

            IReadOnlyCollection <OrchestrationState> results = await this.service.GetManyOrchestrationsAsync(query, cancellationToken);

            return(new OrchestrationStatusQueryResult
            {
                DurableOrchestrationState = results.Select(s => new DurableOrchestrationStatus
                {
                    Name = s.Name,
                    InstanceId = s.OrchestrationInstance.InstanceId,
                    RuntimeStatus = (OrchestrationRuntimeStatus)s.OrchestrationStatus,
                    CustomStatus = s.Status,
                    CreatedTime = s.CreatedTime,
                    LastUpdatedTime = s.LastUpdatedTime,
                    Input = s.Input,
                    Output = s.Output,
                }),
                ContinuationToken = results.Count == query.PageSize ? (query.PageNumber + 1).ToString() : null,
            });
        }
Esempio n. 17
0
        public async Task MultiInstanceQueries()
        {
            DateTime startTime = DateTime.UtcNow;
            string   prefix    = $"{startTime:HHmmss}";

            await Enumerable.Range(0, 5).ParallelForEachAsync(5, i =>
                                                              this.RunOrchestrationAsync(
                                                                  nameof(Functions.Sequence),
                                                                  instanceId: $"{prefix}.sequence.{i}"));

            // Extra delay to account for test flakiness in the GitHub CI (TODO: Why is this necessary?)
            await Task.Delay(TimeSpan.FromSeconds(1));

            DateTime sequencesFinishedTime = SharedTestHelpers.GetCurrentDatabaseTimeUtc();

            await Enumerable.Range(0, 5).ParallelForEachAsync(5, i =>
                                                              this.StartOrchestrationAsync(
                                                                  nameof(Functions.WaitForEvent),
                                                                  input: i.ToString(),
                                                                  instanceId: $"{prefix}.waiter.{i}"));

            IDurableClient client = await this.GetDurableClientAsync();

            // Create one condition object and reuse it for multiple queries
            var condition = new OrchestrationStatusQueryCondition();
            OrchestrationStatusQueryResult result;

            // Return all instances
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            // Test CreatedTimeTo filter
            condition.CreatedTimeTo = startTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Empty(result.DurableOrchestrationState);

            condition.CreatedTimeTo = sequencesFinishedTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(5, result.DurableOrchestrationState.Count());

            condition.CreatedTimeTo = DateTime.UtcNow;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            // Test CreatedTimeFrom filter
            condition.CreatedTimeFrom = DateTime.UtcNow;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Empty(result.DurableOrchestrationState);

            condition.CreatedTimeFrom = sequencesFinishedTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(5, result.DurableOrchestrationState.Count());

            condition.CreatedTimeFrom = startTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            // Test RuntimeStatus filter
            var statusFilters = new HashSet <OrchestrationRuntimeStatus>(new[]
            {
                OrchestrationRuntimeStatus.Failed,
                OrchestrationRuntimeStatus.Pending,
                OrchestrationRuntimeStatus.Terminated
            });

            condition.RuntimeStatus = statusFilters;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Empty(result.DurableOrchestrationState);

            statusFilters.Add(OrchestrationRuntimeStatus.Running);
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(5, result.DurableOrchestrationState.Count());
            Assert.All(result.DurableOrchestrationState, state => Assert.Equal(OrchestrationRuntimeStatus.Running, state.RuntimeStatus));

            statusFilters.Add(OrchestrationRuntimeStatus.Completed);
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            statusFilters.Remove(OrchestrationRuntimeStatus.Running);
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(5, result.DurableOrchestrationState.Count());
            Assert.All(result.DurableOrchestrationState, state => Assert.Equal(OrchestrationRuntimeStatus.Completed, state.RuntimeStatus));

            statusFilters.Clear();
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            // Test InstanceIdPrefix
            condition.InstanceIdPrefix = "Foo";
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Empty(result.DurableOrchestrationState);

            condition.InstanceIdPrefix = prefix;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.Equal(10, result.DurableOrchestrationState.Count());

            // Test PageSize and ContinuationToken
            var instanceIds = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            condition.PageSize = 0;
            while (condition.PageSize++ < 10)
            {
                result = await client.ListInstancesAsync(condition, CancellationToken.None);

                int total = result.DurableOrchestrationState.Count();
                Assert.Equal(condition.PageSize, total);

                // Make sure all instance IDs are unique
                Assert.All(result.DurableOrchestrationState, s => instanceIds.Add(s.InstanceId));

                while (total < 10)
                {
                    condition.ContinuationToken = result.ContinuationToken;
                    result = await client.ListInstancesAsync(condition, CancellationToken.None);

                    int count = result.DurableOrchestrationState.Count();
                    Assert.NotEqual(0, count);
                    Assert.True(count <= condition.PageSize);
                    total += count;
                    Assert.True(total <= 10);
                    Assert.All(result.DurableOrchestrationState, s => instanceIds.Add(s.InstanceId));
                }

                condition.ContinuationToken = null;
            }

            // Test ShowInput
            condition.ShowInput       = true;
            condition.CreatedTimeFrom = sequencesFinishedTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.All(result.DurableOrchestrationState, state => Assert.NotEqual(JValue.CreateNull(), state.Input));

            condition.ShowInput       = false;
            condition.CreatedTimeFrom = startTime;
            result = await client.ListInstancesAsync(condition, CancellationToken.None);

            Assert.All(result.DurableOrchestrationState, state => Assert.Equal(JValue.CreateNull(), state.Input));
        }
        /// <inheritdoc/>
        public async override Task <OrchestrationStatusQueryResult> GetOrchestrationStateWithPagination(OrchestrationStatusQueryCondition condition, CancellationToken cancellationToken)
        {
            var instanceQuery = new InstanceQuery(
                runtimeStatus: condition.RuntimeStatus?.Select(p => (OrchestrationStatus)Enum.Parse(typeof(OrchestrationStatus), p.ToString())).ToArray(),
                createdTimeFrom: (condition.CreatedTimeFrom == default) ? (DateTime?)null : condition.CreatedTimeFrom.ToUniversalTime(),
                createdTimeTo: (condition.CreatedTimeTo == default) ? (DateTime?)null : condition.CreatedTimeTo.ToUniversalTime(),
                instanceIdPrefix: condition.InstanceIdPrefix,
                fetchInput: condition.ShowInput);

            InstanceQueryResult result = await this.Service.QueryOrchestrationStatesAsync(instanceQuery, condition.PageSize, condition.ContinuationToken, cancellationToken);

            return(new OrchestrationStatusQueryResult()
            {
                DurableOrchestrationState = result.Instances.Select(ostate => ProviderUtils.ConvertOrchestrationStateToStatus(ostate)).ToList(),
                ContinuationToken = result.ContinuationToken,
            });
        }