コード例 #1
0
        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);
                }
            });
        }
コード例 #2
0
    static void Main()
    {
        const string channelInvalidate = "cache/invalidate";

        using (var pub = new RedisConnection("127.0.0.1"))
            using (var sub = new RedisSubscriberConnection("127.0.0.1"))
            {
                pub.Open();
                sub.Open();

                sub.Subscribe(channelInvalidate, (channel, data) =>
                {
                    string key = Encoding.UTF8.GetString(data);
                    Console.WriteLine("Invalidated {0}", key);
                });
                Console.WriteLine(
                    "Enter a key to invalidate, or an empty line to exit");
                string line;
                do
                {
                    line = Console.ReadLine();
                    if (!string.IsNullOrEmpty(line))
                    {
                        pub.Publish(channelInvalidate, line);
                    }
                } while (!string.IsNullOrEmpty(line));
            }
    }
コード例 #3
0
    static void Main()
    {
        // IMPORTANT: the "pub" and "sub" can be on entirely separate machines,
        // as long as they are talking to the same server. They are only shown
        // together here for convenience
        using (var sub = new RedisSubscriberConnection("localhost"))
            using (var pub = new RedisConnection("localhost"))
            {
                sub.Open();
                pub.Open();

                sub.Subscribe("busytime", (queue, payload) =>
                {
                    // you don't actually need the payload, probably
                    var received = Encoding.UTF8.GetString(payload);
                    Console.WriteLine("Work to do! Look busy!: " + received);
                });

                string line;
                Console.WriteLine("Enter messages to send, or q to quit");
                while ((line = Console.ReadLine()) != null && line != "q")
                {
                    pub.Publish("busytime", line);
                }
            }
    }
コード例 #4
0
 public void AddHandler <T>(string channel, EventHandler <InterServerEventArgs <T> > handler) where T : struct
 {
     conn.Subscribe(channel, (s, buff) =>
     {
         var message = JsonConvert.DeserializeObject <Message <T> >(Encoding.UTF8.GetString(buff));
         if (message.TargetInst != null &&
             message.TargetInst != InstanceId)
         {
             return;
         }
         handler(this, new InterServerEventArgs <T>(message.InstId, message.Content));
     });
 }
コード例 #5
0
        public virtual async Task Subscribe()
        {
            if (connection.State == RedisConnectionBase.ConnectionState.New)
            {
                await connection.Open();
            }

            await connection.Subscribe(
                channel,
                (key, data) =>
                action(Info.Deserialize <TInfo>(
                           data)));
        }
コード例 #6
0
        private Task ConnectToRedis()
        {
            if (_connection != null)
            {
                _connection.Closed -= OnConnectionClosed;
                _connection.Error  -= OnConnectionError;
                _connection.Dispose();
                _connection = null;
            }

            // Create a new connection to redis with the factory
            RedisConnection connection = _connectionFactory();

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

            try
            {
                Trace.TraceInformation("Connecting...");

                // Start the connection
                return(connection.Open().Then(() =>
                {
                    Trace.TraceInformation("Connection opened");

                    // Create a subscription channel in redis
                    RedisSubscriberConnection channel = connection.GetOpenSubscriberChannel();

                    // Subscribe to the registered connections
                    channel.Subscribe(_key, 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);
                    }

                    Trace.TraceVerbose("Subscribed to event " + _key);

                    _channel = channel;
                    _connection = connection;
                }));
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error connecting to redis - " + ex.GetBaseException());

                return(TaskAsyncHelper.FromError(ex));
            }
        }
コード例 #7
0
 public MyCache(string configuration = "127.0.0.1:6379", int db = 0)
 {
     conn       = ConnectionUtils.Connect(configuration);
     this.db    = db;
     localCache = new MemoryCache("local:" + db.ToString());
     if (conn == null)
     {
         throw new ArgumentException("It was not possible to connect to redis", "configuration");
     }
     sub = conn.GetOpenSubscriberChannel();
     cacheInvalidationChannel = db.ToString() + ":inval";     // note that pub/sub is server-wide; use
                                                              // a channel per DB here
     sub.Subscribe(cacheInvalidationChannel, Invalidate);
 }
コード例 #8
0
 public IAOPResult RegisterDispatcher(IEventDispatcher dispatcher)
 {
     if (!this.dispatchers.ContainsKey(dispatcher))
     {
         lock (this.dispatchers) {
             if (!this.dispatchers.ContainsKey(dispatcher))
             {
                 var redis = new RedisSubscriberConnection(this.Redis.Host, this.Redis.Port);
                 redis.Open();
                 redis.Subscribe(this.NotifyQueueName, (k, r) => dispatcher.OnMessageReceived(this, r));
                 dispatchers.Add(dispatcher, redis);
             }
         }
     }
     return(AOPResult.Success());
 }
コード例 #9
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");
                    }
                }
        }
コード例 #10
0
        private Task ConnectToRedis()
        {
            if (_connection != null)
            {
                _connection.Closed -= OnConnectionClosed;
                _connection.Error  -= OnConnectionError;
                _connection.Dispose();
                _connection = null;
            }

            // Create a new connection to redis with the factory
            RedisConnection connection = _connectionFactory();

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

            try
            {
                _trace.TraceInformation("Connecting...");

                // Start the connection
                return(connection.Open().Then(() =>
                {
                    _trace.TraceInformation("Connection opened");

                    // Create a subscription channel in redis
                    RedisSubscriberConnection channel = connection.GetOpenSubscriberChannel();
                    channel.CompletionMode = ResultCompletionMode.PreserveOrder;

                    // Subscribe to the registered connections
                    return channel.Subscribe(_key, OnMessage).Then(() =>
                    {
                        _trace.TraceVerbose("Subscribed to event " + _key);

                        _channel = channel;
                        _connection = connection;
                    });
                }));
            }
            catch (Exception ex)
            {
                _trace.TraceError("Error connecting to Redis - " + ex.GetBaseException());

                return(TaskAsyncHelper.FromError(ex));
            }
        }
コード例 #11
0
ファイル: RedisQueue.cs プロジェクト: vmaron/Roque
        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);
        }
コード例 #12
0
        public virtual async Task Subscribe(
            string eventName,
            Action <TInfo> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            if (connection.State == RedisConnectionBase.ConnectionState.New)
            {
                await connection.Open();
            }

            var channel = Channel(eventName);

            await connection.Subscribe(
                channel,
                (key, data) => action(Info.Deserialize <TInfo>(data)));
        }
コード例 #13
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");
                }
        }
コード例 #14
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));
                }
            }
        }
コード例 #15
0
        //
        // Listening Algorithm
        //

        /**
         * Register a callback to allow the Redis server to signal when new work is available.
         */
        protected void EnterListeningState()
        {
            Log.Info("Entering listening state.");
            subscriberConnection.Subscribe(configuration.Queue, WorkReady);
        }