Esempio n. 1
0
 public void AddLockRequestToBatch(RequestMessage lockRequest)
 {
     this.lockRequest = lockRequest;
 }
Esempio n. 2
0
 public void AddOperationToBatch(RequestMessage operationMessage)
 {
     this.operationBatch.Add(operationMessage);
 }
Esempio n. 3
0
        private async Task ProcessOperationRequestAsync(RequestMessage request)
        {
            // set context for operation
            this.context.CurrentOperation         = request;
            this.context.CurrentOperationResponse = new ResponseMessage();

            // set the async-local static context that is visible to the application code
            Entity.SetContext(this.context);

            bool operationFailed       = false;
            var  initialOutboxPosition = this.context.OutboxPosition;

            var stopwatch = new System.Diagnostics.Stopwatch();

            stopwatch.Start();

            string exceptionDetails = string.Empty;

            try
            {
                Task invokeTask = this.FunctionInvocationCallback();
                if (invokeTask is Task resultTask)
                {
                    await resultTask;

                    stopwatch.Stop();
                }
                else
                {
                    throw new InvalidOperationException("The WebJobs runtime returned a invocation task that is not awaitable!");
                }
            }
            catch (Exception e)
            {
                stopwatch.Stop();

                exceptionDetails = e.ToString();

                this.context.CaptureApplicationError(e);

                // exception must be sent with response back to caller
                this.context.CurrentOperationResponse.SetExceptionResult(
                    e,
                    this.context.CurrentOperation.Operation,
                    this.errorDataConverter);

                operationFailed = true;
            }

            if (this.RollbackFailedOperations)
            {
                // we write back the entity state after each successful operation
                if (!operationFailed)
                {
                    if (!this.context.TryWriteback(out var errorResponseMessage))
                    {
                        // state serialization failed; create error response and roll back.
                        this.context.CurrentOperationResponse = errorResponseMessage;
                        operationFailed = true;
                    }
                }

                if (operationFailed)
                {
                    // discard changes and don't send any signals
                    this.context.Rollback(initialOutboxPosition);
                }
            }

            // clear the async-local static context that is visible to the application code
            Entity.SetContext(null);

            // read and clear context
            var response = this.context.CurrentOperationResponse;

            this.context.CurrentOperation         = null;
            this.context.CurrentOperationResponse = null;

            if (!operationFailed)
            {
                this.Config.TraceHelper.OperationCompleted(
                    this.context.HubName,
                    this.context.Name,
                    this.context.InstanceId,
                    request.Id.ToString(),
                    request.Operation,
                    this.Config.GetIntputOutputTrace(this.context.RawInput),
                    this.Config.GetIntputOutputTrace(response.Result),
                    stopwatch.Elapsed.TotalMilliseconds,
                    isReplay: false);
            }
            else
            {
                this.Config.TraceHelper.OperationFailed(
                    this.context.HubName,
                    this.context.Name,
                    this.context.InstanceId,
                    request.Id.ToString(),
                    request.Operation,
                    this.Config.GetIntputOutputTrace(this.context.RawInput),
                    exceptionDetails,
                    stopwatch.Elapsed.TotalMilliseconds,
                    isReplay: false);
            }

            // send response
            if (!request.IsSignal)
            {
                var target = new OrchestrationInstance()
                {
                    InstanceId = request.ParentInstanceId, ExecutionId = request.ParentExecutionId
                };
                var jresponse = JToken.FromObject(response, this.messageDataConverter.JsonSerializer);
                this.context.SendResponseMessage(target, request.Id, jresponse, response.IsException);
            }
        }
Esempio n. 4
0
        private async Task ExecuteOutOfProcBatch()
        {
            object outOfProcResults = null;

            Task invokeTask = this.FunctionInvocationCallback();

            if (invokeTask is Task <object> resultTask)
            {
                outOfProcResults = await resultTask;
            }
            else
            {
                throw new InvalidOperationException("The WebJobs runtime returned a invocation task that does not support return values!");
            }

            var jObj = outOfProcResults as JObject;

            if (jObj == null)
            {
                throw new ArgumentException("Out of proc orchestrators must return a valid JSON schema.");
            }

            var outOfProcResult = jObj.ToObject <OutOfProcResult>();

            // update the state
            this.context.State.EntityExists = outOfProcResult.EntityExists;
            this.context.State.EntityState  = outOfProcResult.EntityState;

            // for each operation, emit trace and send response message (if not a signal)
            for (int i = 0; i < this.OperationBatch.Count; i++)
            {
                var request = this.OperationBatch[i];
                var result  = outOfProcResult.Results[i];

                if (!result.IsError)
                {
                    this.Config.TraceHelper.OperationCompleted(
                        this.context.HubName,
                        this.context.Name,
                        this.context.InstanceId,
                        request.Id.ToString(),
                        request.Operation,
                        this.Config.GetIntputOutputTrace(request.Input),
                        this.Config.GetIntputOutputTrace(result.Result),
                        result.DurationInMilliseconds,
                        isReplay: false);
                }
                else
                {
                    this.context.CaptureApplicationError(new OperationErrorException(
                                                             $"Error in operation '{request.Operation}': {result}"));

                    this.Config.TraceHelper.OperationFailed(
                        this.context.HubName,
                        this.context.Name,
                        this.context.InstanceId,
                        request.Id.ToString(),
                        request.Operation,
                        this.Config.GetIntputOutputTrace(request.Input),
                        this.Config.GetIntputOutputTrace(result.Result),
                        result.DurationInMilliseconds,
                        isReplay: false);
                }

                if (!request.IsSignal)
                {
                    var target = new OrchestrationInstance()
                    {
                        InstanceId  = request.ParentInstanceId,
                        ExecutionId = request.ParentExecutionId,
                    };
                    var responseMessage = new ResponseMessage()
                    {
                        Result        = result.Result,
                        ExceptionType = result.IsError ? "Error" : null,
                    };
                    this.context.SendResponseMessage(target, request.Id, responseMessage, !result.IsError);
                }
            }

            // send signal messages
            foreach (var signal in outOfProcResult.Signals)
            {
                var request = new RequestMessage()
                {
                    ParentInstanceId  = this.context.InstanceId,
                    ParentExecutionId = null, // for entities, message sorter persists across executions
                    Id        = Guid.NewGuid(),
                    IsSignal  = true,
                    Operation = signal.Name,
                    Input     = signal.Input,
                };
                var target = new OrchestrationInstance()
                {
                    InstanceId = EntityId.GetSchedulerIdFromEntityId(signal.Target),
                };
                this.context.SendOperationMessage(target, request);
            }
        }
Esempio n. 5
0
        private async Task ProcessOperationRequestAsync(RequestMessage request)
        {
            // set context for operation
            this.context.CurrentOperation         = request;
            this.context.CurrentOperationResponse = new ResponseMessage();

            // set the async-local static context that is visible to the application code
            Entity.SetContext(this.context);

            var stopwatch = new System.Diagnostics.Stopwatch();

            stopwatch.Start();

            string exceptionDetails = string.Empty;

            try
            {
                Task invokeTask = this.FunctionInvocationCallback();
                if (invokeTask is Task resultTask)
                {
                    await resultTask;

                    stopwatch.Stop();
                }
                else
                {
                    throw new InvalidOperationException("The WebJobs runtime returned a invocation task that is not awaitable!");
                }
            }
            catch (Exception e)
            {
                stopwatch.Stop();

                exceptionDetails = e.ToString();

                this.context.CaptureApplicationError(e);

                // exception must be sent with response back to caller
                this.context.CurrentOperationResponse.SetExceptionResult(e, this.context.CurrentOperation.Operation, this.EntityId);
            }

            // clear the async-local static context that is visible to the application code
            Entity.SetContext(null);

            // read and clear context
            var response = this.context.CurrentOperationResponse;

            this.context.CurrentOperation         = null;
            this.context.CurrentOperationResponse = null;

            if (!response.IsException)
            {
                this.Config.TraceHelper.OperationCompleted(
                    this.context.HubName,
                    this.context.Name,
                    this.context.InstanceId,
                    request.Id.ToString(),
                    request.Operation,
                    this.Config.GetIntputOutputTrace(this.context.RawInput),
                    this.Config.GetIntputOutputTrace(response.Result),
                    stopwatch.Elapsed.TotalMilliseconds,
                    isReplay: false);
            }
            else
            {
                this.Config.TraceHelper.OperationFailed(
                    this.context.HubName,
                    this.context.Name,
                    this.context.InstanceId,
                    request.Id.ToString(),
                    request.Operation,
                    this.Config.GetIntputOutputTrace(this.context.RawInput),
                    exceptionDetails,
                    stopwatch.Elapsed.TotalMilliseconds,
                    isReplay: false);
            }

            // send response
            if (!request.IsSignal)
            {
                var target = new OrchestrationInstance()
                {
                    InstanceId = request.ParentInstanceId
                };
                var guid      = request.Id.ToString();
                var jresponse = JToken.FromObject(response, MessagePayloadDataConverter.DefaultSerializer);
                this.context.SendResponseMessage(target, guid, jresponse, !response.IsException);
            }
        }