//private string BuildInvocationFailureMessage(string methodName, object[] arguments) //{ // return string.Concat(new string[] // { // "Failed to invoke target method '", // methodName, // "' with argument types = [", // StringUtils.CollectionToCommaDelimitedString<string>(this.GetArgumentTypes(arguments)), // "], values = [", // StringUtils.CollectionToCommaDelimitedString<object>(arguments), // "]" // }); //} //private System.Collections.Generic.List<string> GetArgumentTypes(object[] arguments) //{ // System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>(); // if (arguments != null) // { // for (int i = 0; i < arguments.Length; i++) // { // list.Add(arguments[i].GetType().ToString()); // } // } // return list; //} protected virtual void HandleResult(AmqpBasedRoute replyRoute, List <object> responses) { if (replyRoute != null) { this._queueClient.BatchPublish(exchangeName: replyRoute.ExchangeName, routingKey: replyRoute.RoutingKey, contentList: responses); } }
public QueuedWorkflowMessageProcessingWorker(IQueueClient queueClient, object listenerObject, MethodInfo listenerMethod, QueuedTransition queuedTransition, QueuedTransition nextQueuedTransition, bool createZombieQueues) { Contract.Requires(queueClient.IsNotNull(), "No queueClient specified: Either specify a non-null value for the 'queueClient' constructor argument."); Contract.Requires(listenerObject.IsNotNull(), "No listenerObject specified: Either specify a non-null value for the 'listenerObject' constructor argument."); Contract.Requires(listenerMethod.IsNotNull(), "No listenerMethod specified: Either specify a non-null value for the 'listenerMethod' constructor argument."); this._queueClient = queueClient; this._listenerObject = listenerObject; this._listenerMethod = listenerMethod; Type inType = this._listenerMethod.GetUniqueAndExpectedInputParameterType(); Type outType = this._listenerMethod.GetReturnValueType(); if (outType == typeof(void) || outType == typeof(Task)) { this._canUseRequestAsResponse = true; } else { this._canUseRequestAsResponse = outType.IsAssignableFrom(inType); } //Receive Route é usada para garantir a criação da rota no RabbitMQ this.ReceiveRoute = new AmqpBasedRoute() { ExchangeName = queuedTransition.ExchangeName, //Criando ExchangeName Default QueueName = queuedTransition.LogicalQueueName + ".Process", //Queue de recebimento (Fila Principal) RoutingKey = queuedTransition.BuildRoutingKey() //Binding Entre a ExchangeName e a Fila }; this.ReceiveRoute.EnsureAll(this._queueClient); if (createZombieQueues) { //Filas Zombie não precisam ser armazenadas em variáveis, só precisam ser configuradas //corretamente no RabbitMQ AmqpBasedRoute zombieConfiguration = new AmqpBasedRoute() { ExchangeName = this.ReceiveRoute.ExchangeName, QueueName = queuedTransition.LogicalQueueName + ".Zombie", RoutingKey = this.ReceiveRoute.RoutingKey }; zombieConfiguration.EnsureAll(this._queueClient); } //Caso não seja um passo final, é necessário armazenar e tratar as respostas para o próximo step if (nextQueuedTransition != null) { this._successResponseRoute = new AmqpBasedRoute() { QueueName = nextQueuedTransition.LogicalQueueName + ".Process", ExchangeName = nextQueuedTransition.ExchangeName, RoutingKey = nextQueuedTransition.BuildRoutingKey(), }; this._successResponseRoute.EnsureAll(this._queueClient); } this._errorFlowStrategy = queuedTransition.ErrorFlowStrategy; //Nesse passo as estratégias são usadas para configurar o comportamento adequado para falhas if (this._errorFlowStrategy == ExceptionStrategy.SendToErrorQueue) { //Se ao encontrar um erro, é necessário enviar para a fila de erro, todo o pipe de erro é criado //isso conta com a criação da fila, e dos bindings no RabbitMQ this._failureResponseRoute = new AmqpBasedRoute() { QueueName = queuedTransition.LogicalQueueName + ".Failure", ExchangeName = this.ReceiveRoute.ExchangeName, RoutingKey = queuedTransition.BuildFailureRoutingKey() }; this._failureResponseRoute.EnsureAll(this._queueClient); } else if (this._errorFlowStrategy == ExceptionStrategy.Requeue) { //Nesse caso, ao gerar um erro na fila a mensagem volta para a fila, portanto //a rota usada é escolhida como a mesma rota de recebimento, forçando um requeue this._failureResponseRoute = this.ReceiveRoute; } else if (this._errorFlowStrategy == ExceptionStrategy.SendToNextStepQueue) { //Nesse caso temos a possibilidade de continuar o fluxo, mesmo que uma //exceção seja lançada. if (this._successResponseRoute == null) { throw new InvalidOperationException("The ErrorFlowStrategy property cannot be setted with SendToNextStepQueue value when current step is a final step."); } this._failureResponseRoute = this._successResponseRoute; } }