示例#1
0
        /// <summary>
        /// Handles workflow queries.
        /// </summary>
        /// <param name="request">The request message.</param>
        /// <returns>The reply message.</returns>
        internal async Task <WorkflowQueryInvokeReply> OnQueryAsync(WorkflowQueryInvokeRequest request)
        {
            await SyncContext.Clear;

            Covenant.Requires <ArgumentNullException>(request != null, nameof(request));

            try
            {
                WorkflowBase.CallContext.Value = WorkflowCallContext.Query;

                var workflow = GetWorkflow(request.ContextId);

                if (workflow != null)
                {
                    Workflow.Current = workflow.Workflow;   // Initialize the ambient workflow information for workflow library code.

                    // Handle built-in queries.

                    switch (request.QueryName)
                    {
                    case TemporalClient.QueryStack:

                        var trace = string.Empty;

                        if (workflow.StackTrace != null)
                        {
                            trace = workflow.StackTrace.ToString();
                        }

                        return(new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result = Client.DataConverter.ToData(trace)
                        });

                    case TemporalClient.QuerySyncSignal:

                        // The arguments for this signal is the (string) ID of the target
                        // signal being polled for status.

                        var syncSignalArgs   = TemporalHelper.BytesToArgs(JsonDataConverter.Instance, request.QueryArgs, new Type[] { typeof(string) });
                        var syncSignalId     = (string)(syncSignalArgs.Length > 0 ? syncSignalArgs[0] : null);
                        var syncSignalStatus = workflow.GetSignalStatus(syncSignalId);

                        Covenant.Assert(false);     // This should never happen

                        if (syncSignalStatus.Completed)
                        {
                            // Indicate that the completed signal has reported the status
                            // to the calling client as well as returned the result, if any.

                            syncSignalStatus.Acknowledged    = true;
                            syncSignalStatus.AcknowledgeTime = DateTime.UtcNow;
                        }

                        return(new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result = Client.DataConverter.ToData(syncSignalStatus)
                        });
                    }

                    // Handle user queries.

                    var method = workflow.Workflow.MethodMap.GetQueryMethod(request.QueryName);

                    if (method != null)
                    {
                        var resultType           = method.ReturnType;
                        var methodParameterTypes = method.GetParameterTypes();

                        var serializedResult = Array.Empty <byte>();

                        if (resultType.IsGenericType)
                        {
                            // Query method returns: Task<T>

                            var result = await NeonHelper.GetTaskResultAsObjectAsync((Task)method.Invoke(workflow, TemporalHelper.BytesToArgs(Client.DataConverter, request.QueryArgs, methodParameterTypes)));

                            serializedResult = Client.DataConverter.ToData(result);
                        }
                        else
                        {
                            // Query method returns: Task

                            await(Task) method.Invoke(workflow, TemporalHelper.BytesToArgs(Client.DataConverter, request.QueryArgs, methodParameterTypes));
                        }

                        return(new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result = serializedResult
                        });
                    }
                    else
                    {
                        return(new WorkflowQueryInvokeReply()
                        {
                            Error = new EntityNotExistsException($"Workflow type [{workflow.GetType().FullName}] does not define a query handler for [queryType={request.QueryName}].").ToTemporalError()
                        });
                    }
                }
                else
                {
                    return(new WorkflowQueryInvokeReply()
                    {
                        Error = new EntityNotExistsException($"Workflow with [contextID={request.ContextId}] does not exist.").ToTemporalError()
                    });
                }
            }
            catch (Exception e)
            {
                log.LogError(e);

                return(new WorkflowQueryInvokeReply()
                {
                    Error = new TemporalError(e)
                });
            }
            finally
            {
                WorkflowBase.CallContext.Value = WorkflowCallContext.None;
            }
        }
示例#2
0
        /// <summary>
        /// Handles workflow queries.
        /// </summary>
        /// <param name="client">The Cadence client.</param>
        /// <param name="request">The request message.</param>
        /// <returns>The reply message.</returns>
        internal static async Task <WorkflowQueryInvokeReply> OnQueryAsync(CadenceClient client, WorkflowQueryInvokeRequest request)
        {
            Covenant.Requires <ArgumentNullException>(client != null);
            Covenant.Requires <ArgumentNullException>(request != null);

            try
            {
                var workflow = GetWorkflow(client, request.ContextId);

                if (workflow != null)
                {
                    var method = workflow.Workflow.MethodMap.GetQueryMethod(request.QueryName);

                    if (method != null)
                    {
                        var result = await(Task <byte[]>)(method.Invoke(workflow, new object[] { request.QueryArgs }));

                        return(new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result = result
                        });
                    }
                    else
                    {
                        return(new WorkflowQueryInvokeReply()
                        {
                            Error = new CadenceEntityNotExistsException($"Workflow type [{workflow.GetType().FullName}] does not define a query handler for [queryType={request.QueryName}].").ToCadenceError()
                        });
                    }
                }
                else
                {
                    return(new WorkflowQueryInvokeReply()
                    {
                        Error = new CadenceEntityNotExistsException($"Workflow with [contextID={request.ContextId}] does not exist.").ToCadenceError()
                    });
                }
            }
            catch (Exception e)
            {
                return(new WorkflowQueryInvokeReply()
                {
                    Error = new CadenceError(e)
                });
            }
        }
示例#3
0
        /// <summary>
        /// Handles workflow queries.
        /// </summary>
        /// <param name="client">The Cadence client.</param>
        /// <param name="request">The request message.</param>
        /// <returns>The reply message.</returns>
        internal static async Task<WorkflowQueryInvokeReply> OnQueryAsync(CadenceClient client, WorkflowQueryInvokeRequest request)
        {
            Covenant.Requires<ArgumentNullException>(client != null, nameof(client));
            Covenant.Requires<ArgumentNullException>(request != null, nameof(request));

            try
            {
                WorkflowBase.CallContext.Value = WorkflowCallContext.Query;

                var workflow = GetWorkflow(client, request.ContextId);

                if (workflow != null)
                {
                    // Handle built-in queries.

                    if (request.QueryName == "__stack_trace")
                    {
                        var trace = string.Empty;

                        if (workflow.StackTrace != null)
                        {
                            trace = workflow.StackTrace.ToString();
                        }

                        return new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result    = NeonHelper.JsonSerializeToBytes(trace)
                        };
                    }

                    // Handle user queries.

                    var method = workflow.Workflow.MethodMap.GetQueryMethod(request.QueryName);

                    if (method != null)
                    {
                        var resultType           = method.ReturnType;
                        var methodParameterTypes = method.GetParameterTypes();

                        var serializedResult = emptyBytes;

                        if (resultType.IsGenericType)
                        {
                            // Query method returns: Task<T>

                            var result = await NeonHelper.GetTaskResultAsObjectAsync((Task)method.Invoke(workflow, client.DataConverter.FromDataArray(request.QueryArgs, methodParameterTypes)));

                            serializedResult = client.DataConverter.ToData(result);
                        }
                        else
                        {
                            // Query method returns: Task

                            await (Task)method.Invoke(workflow, client.DataConverter.FromDataArray(request.QueryArgs, methodParameterTypes));
                        }

                        return new WorkflowQueryInvokeReply()
                        {
                            RequestId = request.RequestId,
                            Result    = serializedResult
                        };
                    }
                    else
                    {
                        return new WorkflowQueryInvokeReply()
                        {
                            Error = new EntityNotExistsException($"Workflow type [{workflow.GetType().FullName}] does not define a query handler for [queryType={request.QueryName}].").ToCadenceError()
                        };
                    }
                }
                else
                {
                    return new WorkflowQueryInvokeReply()
                    {
                        Error = new EntityNotExistsException($"Workflow with [contextID={request.ContextId}] does not exist.").ToCadenceError()
                    };
                }
            }
            catch (Exception e)
            {
                log.LogError(e);

                return new WorkflowQueryInvokeReply()
                {
                    Error = new CadenceError(e)
                };
            }
            finally
            {
                WorkflowBase.CallContext.Value = WorkflowCallContext.None;
            }
        }