예제 #1
0
        public async Task <T> CallAsync <T>(string functionName, object parameter = null) where T : class
        {
            var request = new AmqpRpcRequest()
            {
                Method     = functionName,
                Parameters = parameter,
                Type       = RpcRequestType.Call
            };

            return(await this.SendRequestAsync <T>(request));
        }
예제 #2
0
        public async Task NotifyAsync(string functionName, object parameter = null)
        {
            var request = new AmqpRpcRequest()
            {
                Method     = functionName,
                Parameters = parameter,
                Type       = RpcRequestType.Notify
            };

            await this.SendRequestAsync <object>(request);
        }
예제 #3
0
        private async Task <T> SendRequestAsync <T>(AmqpRpcRequest request) where T : class
        {
            var _message = new Message()
            {
                BodySection = new AmqpValue <AmqpRpcRequest>(request)
            };
            var id = Guid.NewGuid().ToString();

            _message.Properties = new Properties()
            {
                Subject       = this._subject,
                To            = this._amqpNode,
                ReplyTo       = request.Type.Equals(RpcRequestType.Call) ? this._clientReceiveAddress : string.Empty,
                MessageId     = id,
                CorrelationId = id
            };
            _message.Header = new Header()
            {
                Ttl = this._timeout
            };
            _ = this._sender.SendAsync(_message);
            if (request.Type.Equals(RpcRequestType.Call))
            {
                try
                {
                    var tcs = new TaskCompletionSource <T>();
                    this._pendingRequests.TryAdd(id, new PendingRequest <T>(tcs));
                    return(await tcs.Task.TimeoutAfterAsync <T>(timeout : unchecked ((int)this._timeout)));
                }
                catch (TimeoutException)
                {
                    this._isTimedout = true;
                    throw new AmqpRpcRequestTimeoutException($"Request timedout while executing {request.Method}");
                }
            }
            return(null);
        }
예제 #4
0
        private async void ProcessIncomingRpcRequestAsync(IReceiverLink receiver, Message message)
        {
            //Accept the message since we would be replying using sender, hence disposition does not make sense
            await Task.Run(async() =>
            {
                receiver.Accept(message);
                //Deserialize the body
                AmqpRpcRequest _rpcRequest = message.GetBody <AmqpRpcRequest>();
                string _replyTo            = message.Properties.ReplyTo;
                string _correlationId      = message.Properties.CorrelationId;

                if (!_rpMethodTypes.Contains(_rpcRequest.Type))
                {
                    Log.Error($"Invalid request type received: {_rpcRequest.Type}");
                    await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: new AmqpRpcInvalidRpcTypeException(_rpcRequest.Type));
                    return;
                }
                if (string.IsNullOrEmpty(_rpcRequest.Method))
                {
                    Log.Error("Missing RPC function call name: {@_rpcRequest}", _rpcRequest);
                    await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: new AmqpRpcMissingFunctionNameException(JsonConvert.SerializeObject(_rpcRequest)));
                    return;
                }
                if (!this._serverFunctions.ContainsKey(_rpcRequest.Method))
                {
                    Log.Error($"Unknown RPC method request received: {_rpcRequest.Method}");
                    await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: new AmqpRpcUnknownFunctionException($"{_rpcRequest.Method} is not bound to remote server"));
                    return;
                }
                var _requestObjectType = this._serverFunctions.SingleOrDefault(x => x.Key.Equals(_rpcRequest.Method));
                if (_requestObjectType.Value == null)
                {
                    Log.Error($"Unknown RPC method request received: {_rpcRequest.Method}");
                    await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: new AmqpRpcUnknownFunctionException($"{_rpcRequest.Method} is not bound to remote server"));
                    return;
                }

                var _methodParameter = this._utility.PeeloutAmqpWrapper(deserializationType: _requestObjectType.Value.RequestParameterType, parameters: _rpcRequest.Parameters);
                var _classInstance   = Activator.CreateInstance(_requestObjectType.Value.FunctionWrapperType);
                MethodInfo _method   = _requestObjectType.Value.FunctionWrapperType.GetMethod(_requestObjectType.Key);

                var _asyncAttribute = _method.GetCustomAttribute <AsyncStateMachineAttribute>();
                var _isAsync        = (_asyncAttribute != null) || (_method.ReturnType.BaseType.Equals(typeof(Task)));

                try
                {
                    if (!(_methodParameter is null) && _method.GetParameters().Length > 0)
                    {
                        //TODO: check for missing properties from rpc calls
                        //await this.SendResponse(replyTo: _replyTo, correlationId: _correlationId, _rpcRequest.type, null, new AmqpRpcUnknowParameterException($"{_rpcRequest.method} invokation failed, mismatch in parameter"));
                        object _rtnVal = null;
                        try
                        {
                            if (_isAsync)
                            {
                                _rtnVal = await(dynamic) _method.Invoke(_classInstance, new[] { _methodParameter });
                            }
                            else
                            {
                                _rtnVal = _method.Invoke(_classInstance, new[] { _methodParameter });
                            }
                            await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: _rtnVal, ex: null);
                        }
                        catch (Exception ex)
                        {
                            await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: ex);
                            return;
                        }
                    }
                    else if (_methodParameter is null && _method.GetParameters().Length.Equals(0))
                    {
                        object _rtnVal = null;
                        try
                        {
                            if (_isAsync)
                            {
                                _rtnVal = await(dynamic) _method.Invoke(_classInstance, null);
                            }
                            else
                            {
                                _rtnVal = _method.Invoke(_classInstance, null);
                            }
                            await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: _rtnVal, ex: null);
                        }
                        catch (Exception ex)
                        {
                            await this.SendResponseAsync(replyTo: _replyTo, correlationId: _correlationId, requestType: _rpcRequest.Type, response: null, ex: ex);
                            return;
                        }
                    }