public RedisMessageBus(string server, int port, string password, int db, IEnumerable<string> keys, IDependencyResolver resolver)
            : base(resolver)
        {
            _db = db;
            _keys = keys.ToArray();

            _connection = new RedisConnection(host: server, port: port, password: password);

            _connection.Closed += OnConnectionClosed;
            _connection.Error += OnConnectionError;

            // Start the connection
            _connectTask = _connection.Open().Then(() => {
                // Create a subscription channel in redis
                _channel = _connection.GetOpenSubscriberChannel();

                // Subscribe to the registered connections
                _channel.Subscribe(_keys, OnMessage);

                // Dirty hack but it seems like subscribe returns before the actual
                // subscription is properly setup in some cases
                while (_channel.SubscriptionCount == 0) {
                    Thread.Sleep(500);
                }
            });
        }
        /// <summary>
        /// Subscribe to perform some operation when a change to the preferred/active node is broadcast.
        /// </summary>
        public static void SubscribeToMasterSwitch(RedisSubscriberConnection connection, Action<string> handler)
        {
            if (connection == null) throw new ArgumentNullException("connection");
            if (handler == null) throw new ArgumentNullException("handler");

            connection.Subscribe(RedisMasterChangedChannel, (channel, message) => handler(Encoding.UTF8.GetString(message)));
        }
        private void Subscribe()
        {
            channel = gateway.GetConnection().GetOpenSubscriberChannel();
            channel.Closed += OnChannelClosed;

            channel.Subscribe(EventKey, OnMessageRecieved);
        }
        /// <summary>
        /// Subscribe to perform some operation when a change to the preferred/active node is broadcast.
        /// </summary>
        public static void SubscribeToMasterSwitch(RedisSubscriberConnection connection, Action <string> handler)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            connection.Subscribe(RedisMasterChangedChannel, (channel, message) => handler(Encoding.UTF8.GetString(message)));
        }
Exemple #5
0
        private void TestSubscriberNameOnRemote(bool setName)
        {
            string id = Config.CreateUniqueName();

            using (var pub = new RedisConnection(Config.RemoteHost, allowAdmin: true))
            using (var sub = new RedisSubscriberConnection(Config.RemoteHost))
            {
                List<string> errors = new List<string>();
                EventHandler<BookSleeve.ErrorEventArgs> errorHandler = (sender, args) =>
                {
                    lock (errors) errors.Add(args.Exception.Message);
                };
                pub.Error += errorHandler;
                sub.Error += errorHandler;

                if (setName)
                {
                    pub.Name = "pub_" + id;
                    sub.Name = "sub_" + id;
                }
                int count = 0;
                var subscribe = sub.Subscribe("foo"+id, (key,payload) => Interlocked.Increment(ref count));

                Task pOpen = pub.Open(), sOpen = sub.Open();
                pub.WaitAll(pOpen, sOpen, subscribe);

                Assert.AreEqual(0, Interlocked.CompareExchange(ref count, 0, 0), "init message count");
                pub.Wait(pub.Publish("foo" + id, "hello"));

                PubSub.AllowReasonableTimeToPublishAndProcess();
                var clients = setName ? pub.Wait(pub.Server.ListClients()) : null;
                Assert.AreEqual(1, Interlocked.CompareExchange(ref count, 0, 0), "got message");
                lock (errors)
                {
                    foreach (var error in errors)
                    {
                        Console.WriteLine(error);
                    }
                    Assert.AreEqual(0, errors.Count, "zero errors");
                }
                if (setName)
                {
                    Assert.AreEqual(1, clients.Count(x => x.Name == pub.Name), "pub has name");
                    Assert.AreEqual(1, clients.Count(x => x.Name == sub.Name), "sub has name");
                }
            }
        }
Exemple #6
0
        public void TestForcedSubscriberName()
        {
            using (var conn = Config.GetUnsecuredConnection(allowAdmin: true, open: true, waitForOpen: true))
            using (var sub = new RedisSubscriberConnection(conn.Host, conn.Port))
            {
                var task = sub.Subscribe("foo", delegate { });
                string name = Config.CreateUniqueName();
                sub.Name = name;
                sub.SetServerVersion(new Version("2.6.9"), ServerType.Master);
                sub.Wait(sub.Open());
                sub.Wait(task);
                Assert.AreEqual(1, sub.SubscriptionCount);

                if (!conn.Features.ClientName) Assert.Inconclusive();
                var clients = conn.Wait(conn.Server.ListClients()).Where(c => c.Name == name).ToList();
                Assert.AreEqual(1, clients.Count, "number of clients");
            }
        }
Exemple #7
0
        public override string[] GetSubscribersForEvent(string target, string eventName)
        {
            string[] subscribers;
            string eventKey = target + ":" + eventName;
            RedisConnection connection = null;

            if (_SubscribedToSubscribersChangesChannel != null &&
                _SubscribedToSubscribersChangesChannel.State != RedisConnectionBase.ConnectionState.Open &&
                _SubscribedToSubscribersChangesChannel.State != RedisConnectionBase.ConnectionState.Opening)
            {
                // connection dropped, create a new one
                _SubscribedToSubscribersChangesChannel = null;
                ClearSubscribersCache();
            }
            if (_SubscribedToSubscribersChangesChannel == null)
            {
                if (connection == null)
                {
                    connection = Connection.GetOpen();
                }
                _SubscribedToSubscribersChangesChannel = connection.GetOpenSubscriberChannel();
                _SubscribedToSubscribersChangesChannel.Subscribe(GetRedisKey("events:subscriberschanges"), (message, bytes) =>
                {
                    RoqueTrace.Source.Trace(TraceEventType.Information, "[REDIS] Subscribers added to {0}, clearing subscribers cache", Name);
                    ClearSubscribersCache();
                });
                RoqueTrace.Source.Trace(TraceEventType.Verbose, "[REDIS] Listening for subscribers changes on queue {0}", Name);
            }

            if (DateTime.Now.Subtract(_SubscribersCacheLastClear) > (SubscribersCacheExpiration ?? DefaultSubscribersCacheExpiration))
            {
                ClearSubscribersCache();
            }

            if (!_SubscribersCache.TryGetValue(eventKey, out subscribers))
            {
                if (connection == null)
                {
                    connection = Connection.GetOpen();
                }
                subscribers = connection.SortedSets.Range(0, GetRedisKey("events:{0}:subscribers", eventKey), 0, -1).Result
                    .Select(set => Encoding.UTF8.GetString(set.Key)).ToArray();
                _SubscribersCache[eventKey] = subscribers;
            }
            return subscribers;
        }
Exemple #8
0
        protected override void EnqueueJsonEvent(string data, string target, string eventName)
        {
            var connection = GetOpenConnection();

            string[] subscribers;
            string eventKey = target + ":" + eventName;

            if (_SubscribedToSubscribersChangesChannel != null &&
                _SubscribedToSubscribersChangesChannel.State != RedisConnectionBase.ConnectionState.Open &&
                _SubscribedToSubscribersChangesChannel.State != RedisConnectionBase.ConnectionState.Opening)
            {
                // connection dropped, create a new one
                _SubscribedToSubscribersChangesChannel = null;
                ClearSubscribersCache();
            }
            if (_SubscribedToSubscribersChangesChannel == null)
            {
                _SubscribedToSubscribersChangesChannel = connection.GetOpenSubscriberChannel();
                _SubscribedToSubscribersChangesChannel.Subscribe(GetRedisKey("events:subscriberschanges"), (message, bytes) =>
                {
                    if (Roque.Core.RoqueTrace.Switch.TraceInfo)
                    {
                        Trace.TraceInformation("[REDIS] Subscribers added to {0}, clearing subscribers cache", Name);
                    }
                    ClearSubscribersCache();
                });
                if (Roque.Core.RoqueTrace.Switch.TraceVerbose)
                {
                    Trace.TraceInformation("[REDIS] Listening for subscribers changes on queue {0}", Name);
                }
            }

            if (DateTime.Now.Subtract(_SubscribersCacheLastClear) > (SubscribersCacheExpiration ?? DefaultSubscribersCacheExpiration))
            {
                ClearSubscribersCache();
            }

            if (!_SubscribersCache.TryGetValue(eventKey, out subscribers))
            {
                subscribers = connection.SortedSets.Range(0, GetRedisKey("events:{0}:subscribers", eventKey), 0, -1).Result
                    .Select(set => Encoding.UTF8.GetString(set.Key)).ToArray();
                _SubscribersCache[eventKey] = subscribers;
            }
            if (subscribers == null || subscribers.Length == 0)
            {
                if (RoqueTrace.Switch.TraceVerbose)
                {
                    Trace.TraceInformation(string.Format("No subscriber for this event, enqueue cancelled. Event: {0}:{1}, Queue:{2}", target, eventName, Name));
                }
                Thread.Sleep(10000);
            }
            else
            {
                foreach (var subscriber in subscribers)
                {
                    connection.Lists.AddFirst(0, GetRedisKeyForQueue(subscriber), data);
                }
                if (RoqueTrace.Switch.TraceVerbose)
                {
                    Trace.TraceInformation(string.Format("Event published to queues: {0}. Event: {1}:{2}", string.Join(", ", subscribers), target, eventName));
                }
            }
        }