示例#1
0
        private void CoreConnection_Connected(string appId)
        {
            try
            {
                var exchangeName = Name + ".direct";
                var consumer     = new ConsumerParam()
                {
                    ExchangeParam = new ChannelExchangeParam()
                    {
                        Name = exchangeName,
                        Type = ExchangeTypes.EXCHANGETYPE_DIRECT,
                    },
                    QueueParam = new ChannelQueueParam()
                    {
                        Name       = exchangeName + "." + appId,
                        AutoDelete = true
                    }
                };

                CoreConnection.Listen(consumer, (msg) =>
                {
                    var str = Encoding.UTF8.GetString(msg.Content);
                    msg.Ack();
                    Trace.TraceInformation($"Listen ({Name}): {str}");
                    if (str == "Exit")
                    {
                        lockEvent.Set();
                    }
                    if (QuestionAnswerDictionary.ContainsKey(str))
                    {
                        Say(QuestionAnswerDictionary[str]);
                        if (QuestionAnswerDictionary[str] == "Exit")
                        {
                            lockEvent.Set();
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Неизвестное сообщение");
                    }
                });

                if (!string.IsNullOrEmpty(SayMessage) && QuestionAnswerDictionary.ContainsKey(SayMessage))
                {
                    Say(SayMessage);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());
                throw;
            }
        }
示例#2
0
        /// <summary>
        /// Прослушивание очереди сообщений
        /// </summary>
        /// <param name="cparam">Парамеры создания обмена, очереди и подписчика</param>
        /// <param name="callback">Функция обратного вызова при получении сообщения</param>
        /// <returns></returns>
        public string Listen(ConsumerParam cparam, Action <ReceivedMessageEventArgs> callback)
        {
            if (cparam?.QueueParam == null)
            {
                throw new CoreException("QueueParam not declared");
            }
            var default_durable = Configuration.MQ.durable.HasValue ? Configuration.MQ.durable.Value : false;

            channel.QueueDeclare(cparam.QueueParam.Name,
                                 cparam.QueueParam.Durable ?? default_durable,
                                 cparam.QueueParam.Exclusive,
                                 cparam.QueueParam.AutoDelete,
                                 cparam.QueueParam.Arguments);
            //Queue declare
            Trace.TraceInformation($"Declare queue [{cparam.QueueParam.Name}]. Options: {cparam.QueueParam.ToJson()}");

            if (cparam.ExchangeParam != null)
            {
                channel.ExchangeDeclare(cparam.ExchangeParam.Name,
                                        cparam.ExchangeParam.Type ?? ExchangeTypes.EXCHANGETYPE_DIRECT,
                                        cparam.ExchangeParam.Durable ?? default_durable,
                                        cparam.ExchangeParam.AutoDelete,
                                        cparam.ExchangeParam.Arguments);

                //Exchange declare
                Trace.TraceInformation($"Bind queue [{cparam.QueueParam.Name}] to exchange [{cparam.ExchangeParam.Name}({cparam.ExchangeParam.Type})]. AppId=[{AppId.CurrentUID}] ");

                //Bind queue and exchange
                channel.QueueBind(cparam.QueueParam.Name, cparam.ExchangeParam.Name, AppId.CurrentUID);
            }
            //create consumer and subscribe

            var consumer = new EventingBasicConsumer(channel);

            if (!string.IsNullOrEmpty(cparam.ConsumerTag))
            {
                consumer.ConsumerTag = consumer.ConsumerTag;
            }
            consumer.Received += (model, ea) =>
            {
                if (callback != null)
                {
                    //Ack Nack with try-catch? check if throw exception
                    var msg = new ReceivedMessageEventArgs(ea,
                                                           () =>
                    {
                        try
                        {
                            channel.BasicAck(ea.DeliveryTag, multiple: false);
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceWarning($"Ask error:{ex}");
                        }
                    },
                                                           (autoRepeat) =>
                    {
                        try
                        {
                            channel.BasicNack(ea.DeliveryTag, multiple: false, requeue: autoRepeat);
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceWarning($"Nask error:{ex}");
                        }
                    });

                    callback.Invoke(msg);
                }
            };

            return(channel.BasicConsume(cparam.QueueParam.Name, cparam.AutoAck, consumer));
        }
示例#3
0
        private void Resolver_Started(string obj)
        {
            Trace.TraceInformation("Resolver started");

            //Self resolving timeout, exiting ...
            int timeout  = Config.Starter.registerselftimeout ?? 10000;
            var register = Resolver.RegisterSelf();

            if (Task.WhenAny(register, Task.Delay(timeout)).Result != register)
            {
                throw new CoreException("Resolver self register timeout expired!");
            }

            var links = register.Result;

            Trace.TraceInformation("Self links resolved");

            int queueInc = 2;

            if (links != null)
            {
                foreach (var link in links)
                {
                    var exchangeName = ExchangeTypes.GetExchangeName(link.name, link.type, null);

                    Trace.TraceInformation($"Bind {exchangeName} start..");

                    ConsumerParam options = new ConsumerParam();
                    options.QueueParam = new ChannelQueueParam()
                    {
                        AutoDelete = Config.MQ.autodelete ?? false,
                    };
                    if (Config.MQ.queue.ttl.HasValue)
                    {
                        options.QueueParam.SetExpiresMs(Config.MQ.queue.ttl.Value);
                    }
                    switch (link.type)
                    {
                    case LinkTypes.LINK_EXCHANGE:
                    {
                        ExchangeConnectionString = exchangeName;
                        options.QueueParam.Name  = $"{exchangeName}.{AppId}";
                        options.ExchangeParam    = new ChannelExchangeParam()
                        {
                            Name       = exchangeName,
                            AutoDelete = Config.MQ.autodelete ?? false
                        };
                        if (Config.MQ.exchange.ttl.HasValue)
                        {
                            options.ExchangeParam.SetExpiresMs(Config.MQ.exchange.ttl.Value);
                        }
                    }
                    break;

                    case LinkTypes.LINK_QUEUE:
                    {
                        QueueConnectionString   = exchangeName;
                        options.QueueParam.Name = exchangeName;
                    }
                    break;

                    default: { Trace.TraceWarning($"Unknow link type: [{link.type}]"); continue; }
                    }

                    //Максимальный пул одновременных сообщений контролируется параметром ru:spinosa:mq:prefetch
                    //т.е. максимальным числом полученных сообщений оставленных без ответа
                    Connection.Listen(options, (ea) =>
                    {
                        Task.Run(() => this.HandleMessage(ea))
                        .ContinueWith(res => { this.HandleMessageErrors?.Invoke(ea, res.Exception); }, TaskContinuationOptions.OnlyOnFaulted);
                    });

                    Trace.TraceInformation($"Bind {exchangeName} successed");
                    queueInc--;
                }
            }

            if (queueInc == 0)
            {
                this.running = true;
                //запускаем обновление кэша только если удалось получить собственные ссылки т.к. это подтверждает, что оператор запущен и имеет смысл к нему обращаться
                //

                if (Config.Starter.pingperiod_ms.HasValue)
                {
                    Trace.TraceInformation($"RunRefreshCache started {Config.Starter.pingperiod_ms.Value}ms");
                    Resolver.RunRefreshCache();
                }
                Started?.Invoke(AppId);
            }
            else
            {
                throw new CoreException("Self links bind error:  queueInc!=0 ");
            }
        }
示例#4
0
        private void Connection_Connected(string appId)
        {
            var refreshInterval = cfg_starter.pingperiod_ms;

            var cparam = new ConsumerParam()
            {
                QueueParam = new ChannelQueueParam()
                {
                    Name       = $"{cfg_starter._this._namespace}.{cfg_starter._this.servicename}.resolver.{appId}",
                    AutoDelete = true,
                    Durable    = true
                },
                ExchangeParam = new ChannelExchangeParam()
                {
                    Name       = cfg_starter.responseexchangename,
                    Type       = ExchangeTypes.EXCHANGETYPE_DIRECT,
                    AutoDelete = false,
                    Durable    = true
                }
            };

            if (Configuration.MQ.queue.ttl.HasValue)
            {
                cparam.QueueParam.SetExpiresMs(Configuration.MQ.queue.ttl.Value);
            }
            if (Configuration.MQ.exchange.ttl.HasValue)
            {
                cparam.ExchangeParam.SetExpiresMs(Configuration.MQ.exchange.ttl.Value);
            }

            Connection.Listen(cparam, (msg) =>
            {
                //очередь принимает массив ссылок (links)
                var responceStr = System.Text.Encoding.UTF8.GetString(msg.Content);
                var responce    = responceStr.FromJson <List <ResolverEntry> >();

                if (responce?.Any() ?? false)
                {
                    //по каждой ссылке
                    foreach (var element in responce)
                    {
                        //ключ -  имя сервиса с версией
                        var key = GetKey(element.Namespace, element.service, element.version ?? 0);
                        try
                        {
                            if (element.result == true)
                            {
                                var links = element?.link;

                                if (links == null)
                                {
                                    throw new CoreException($"Resolver queue: Empty links for service. Key: {key}");
                                }
                                //если не self очереди - кэшируем
                                if (element.type != CacheItem.SELF_TOKEN)
                                {
                                    //создаем элемент в кэше
                                    var cache_item = new CacheItem()
                                    {
                                        Namespace   = element.Namespace,
                                        service     = element.service,
                                        version     = element.version,
                                        sub_version = element.sub_version,
                                        self_link   = false,
                                        links       = links
                                    };
                                    AddToLinkCache(key, cache_item);
                                }
                                //отвечаем на запросы
                                var tsc = GetPengingContext(key);
                                if (tsc != null)
                                {
                                    tsc.SetResult(links.ToArray());
                                }
                            }
                            else
                            {
                                throw new CoreException($"Resolver queue: response element result is false. Key: {key}");
                            }
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceWarning(($"Resolver queue error: {ex}"));
                            var tsc = GetPengingContext(key);
                            tsc?.SetException(ex);
                        }
                        finally
                        {
                            RemovePengingElement(key);
                        }
                    }
                }
                msg.Ack();
            });

            Bind = true;
            //SendToOperator(true).Wait();
            //SendToOperator(false).Wait();

            Started?.Invoke(AppId);
            Trace.TraceInformation("Resolver queue created");
        }