private async Task <HttpResponseMessage> HandleRewindInstanceRequestAsync(
            HttpRequestMessage request,
            string instanceId)
        {
            IDurableOrchestrationClient client = this.GetClient(request);

            DurableOrchestrationStatus status = await client.GetStatusAsync(instanceId);

            if (status == null)
            {
                return(request.CreateResponse(HttpStatusCode.NotFound));
            }

            switch (status.RuntimeStatus)
            {
            case OrchestrationRuntimeStatus.Canceled:
            case OrchestrationRuntimeStatus.Terminated:
            case OrchestrationRuntimeStatus.Completed:
                return(request.CreateResponse(HttpStatusCode.Gone));
            }

            string reason = request.GetQueryNameValuePairs()["reason"];

#pragma warning disable 0618
            await client.RewindAsync(instanceId, reason);

#pragma warning restore 0618

            return(request.CreateResponse(HttpStatusCode.Accepted));
        }
        internal async Task <HttpResponseMessage> WaitForCompletionOrCreateCheckStatusResponseAsync(
            HttpRequestMessage request,
            string instanceId,
            OrchestrationClientAttribute attribute,
            TimeSpan timeout,
            TimeSpan retryInterval)
        {
            if (retryInterval > timeout)
            {
                throw new ArgumentException($"Total timeout {timeout.TotalSeconds} should be bigger than retry timeout {retryInterval.TotalSeconds}");
            }

            HttpManagementPayload httpManagementPayload = this.GetClientResponseLinks(request, instanceId, attribute?.TaskHub, attribute?.ConnectionName);

            DurableOrchestrationClientBase client = this.GetClient(request);
            Stopwatch stopwatch = Stopwatch.StartNew();

            while (true)
            {
                DurableOrchestrationStatus status = await client.GetStatusAsync(instanceId);

                if (status != null)
                {
                    if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
                    {
                        return(request.CreateResponse(HttpStatusCode.OK, status.Output));
                    }

                    if (status.RuntimeStatus == OrchestrationRuntimeStatus.Canceled ||
                        status.RuntimeStatus == OrchestrationRuntimeStatus.Failed ||
                        status.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
                    {
                        return(await this.HandleGetStatusRequestAsync(request, instanceId));
                    }
                }

                TimeSpan elapsed = stopwatch.Elapsed;
                if (elapsed < timeout)
                {
                    TimeSpan remainingTime = timeout.Subtract(elapsed);
                    await Task.Delay(remainingTime > retryInterval?retryInterval : remainingTime);
                }
                else
                {
                    return(this.CreateCheckStatusResponseMessage(
                               request,
                               instanceId,
                               httpManagementPayload.StatusQueryGetUri,
                               httpManagementPayload.SendEventPostUri,
                               httpManagementPayload.TerminatePostUri,
                               httpManagementPayload.RewindPostUri,
                               httpManagementPayload.PurgeHistoryDeleteUri));
                }
            }
        }
        async Task <string> IDurableOrchestrationClient.RestartAsync(string instanceId, bool restartWithNewInstanceId)
        {
            DurableOrchestrationStatus status = await((IDurableOrchestrationClient)this).GetStatusAsync(instanceId, showHistory: false, showHistoryOutput: false, showInput: true);

            if (status == null)
            {
                throw new ArgumentException($"An orchestrastion with the instanceId {instanceId} was not found.");
            }

            return(restartWithNewInstanceId ? await((IDurableOrchestrationClient)this).StartNewAsync(orchestratorFunctionName: status.Name, status.Input)
                : await((IDurableOrchestrationClient)this).StartNewAsync(orchestratorFunctionName: status.Name, instanceId: status.InstanceId, status.Input));
        }
Beispiel #4
0
 private StatusResponsePayload ConvertFrom(DurableOrchestrationStatus status)
 {
     return(new StatusResponsePayload
     {
         InstanceId = status.InstanceId,
         RuntimeStatus = status.RuntimeStatus.ToString(),
         Input = status.Input,
         CustomStatus = status.CustomStatus,
         Output = status.Output,
         CreatedTime = status.CreatedTime.ToString("s") + "Z",
         LastUpdatedTime = status.LastUpdatedTime.ToString("s") + "Z",
         HistoryEvents = status.History,
     });
 }
        private async Task <HttpResponseMessage> HandleDeleteHistoryByIdRequestAsync(
            HttpRequestMessage request,
            string instanceId)
        {
            IDurableOrchestrationClient client = this.GetClient(request);
            DurableOrchestrationStatus  status = await client.GetStatusAsync(instanceId, showHistory : false);

            if (status == null)
            {
                return(request.CreateResponse(HttpStatusCode.NotFound));
            }

            PurgeHistoryResult purgeHistoryResult = await client.PurgeInstanceHistoryAsync(instanceId);

            return(request.CreateResponse(HttpStatusCode.OK, purgeHistoryResult));
        }
        private async Task <HttpResponseMessage> HandleRaiseEventRequestAsync(
            HttpRequestMessage request,
            string instanceId,
            string eventName)
        {
            IDurableOrchestrationClient client = this.GetClient(request);

            DurableOrchestrationStatus status = await client.GetStatusAsync(instanceId);

            if (status == null)
            {
                return(request.CreateResponse(HttpStatusCode.NotFound));
            }

            switch (status.RuntimeStatus)
            {
            case OrchestrationRuntimeStatus.Failed:
            case OrchestrationRuntimeStatus.Canceled:
            case OrchestrationRuntimeStatus.Terminated:
            case OrchestrationRuntimeStatus.Completed:
                return(request.CreateResponse(HttpStatusCode.Gone));
            }

            string mediaType = request.Content.Headers.ContentType?.MediaType;

            if (!string.Equals(mediaType, "application/json", StringComparison.OrdinalIgnoreCase))
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Only application/json request content is supported"));
            }

            string stringData = await request.Content.ReadAsStringAsync();

            object eventData;

            try
            {
                eventData = !string.IsNullOrEmpty(stringData) ? JToken.Parse(stringData) : null;
            }
            catch (JsonReaderException e)
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid JSON content", e));
            }

            await client.RaiseEventAsync(instanceId, eventName, eventData);

            return(request.CreateResponse(HttpStatusCode.Accepted));
        }
        internal DurableEntityStatus(DurableOrchestrationStatus orchestrationStatus)
        {
            this.EntityId          = EntityId.GetEntityIdFromSchedulerId(orchestrationStatus.InstanceId);
            this.LastOperationTime = orchestrationStatus.LastUpdatedTime;

            if (orchestrationStatus?.Input is JObject input)
            {
                SchedulerState state = input.ToObject <SchedulerState>();
                if (state?.EntityState != null)
                {
                    try
                    {
                        // Entity state is expected to be JSON-compatible
                        this.State = JToken.Parse(state.EntityState);
                    }
                    catch (JsonException)
                    {
                        // Just in case the above assumption is ever wrong, fallback to a raw string
                        this.State = state.EntityState;
                    }
                }
            }
        }