public async Task SubscribeAsync(string key, Action <int, RedisMessage> onMessage) { _trace.TraceInformation("Subscribing to key: " + key); var channel = await _redisSubscriber.SubscribeAsync(key); channel.OnMessage(channelMessage => { var message = RedisMessage.FromBytes(channelMessage.Message, _trace); onMessage(0, message); // Save the last message id in just in case redis shuts down _latestMessageId = message.Id; }); }
private void OnMessage(int streamIndex, RedisMessage message) { // locked to avoid overlapping calls (even though we have set the mode // to preserve order on the subscription) lock (_callbackLock) { if (lastId.HasValue && message.Id < lastId.Value) { _trace.TraceEvent(TraceEventType.Error, 0, $"ID regression occurred. The next message ID {message.Id} was less than the previous message {lastId.Value}"); } lastId = message.Id; OnReceived(streamIndex, message.Id, message.ScaleoutMessage); } }
public static RedisMessage FromBytes(byte[] data, TraceSource trace) { using (var stream = new MemoryStream(data)) { var message = new RedisMessage(); // read message id from memory stream until SPACE character var messageIdBuilder = new StringBuilder(20); do { // it is safe to read digits as bytes because they encoded by single byte in UTF-8 int charCode = stream.ReadByte(); if (charCode == -1) { trace.TraceVerbose("Received Message could not be parsed."); throw new EndOfStreamException(Resources.Error_EndOfStreamRedis); } char c = (char)charCode; if (c == ' ') { message.Id = ulong.Parse(messageIdBuilder.ToString(), CultureInfo.InvariantCulture); messageIdBuilder = null; } else { messageIdBuilder.Append(c); } }while (messageIdBuilder != null); var binaryReader = new BinaryReader(stream); int count = binaryReader.ReadInt32(); byte[] buffer = binaryReader.ReadBytes(count); message.ScaleoutMessage = ScaleoutMessage.FromBytes(buffer); return(message); } }