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); } }); }
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)); } }
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); } } }
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)); }); }
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))); }
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)); } }
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); }
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()); }
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"); } } }
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)); } }
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); }
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))); }
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"); } }
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)); } } }
// // 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); }