private async Task <RedisMessage <T> > GetMessageAsync() { try { var listItem = await _db.ListRightPopLeftPushAsync(_queueName, RedisQueueConventions.GetProcessingQueueName(_queueName)).ConfigureAwait(false); if (listItem.IsNullOrEmpty) { return(null); } var message = _redisConfiguration.MessageSerializer.Deserialize <T>(listItem); var hashKey = RedisQueueConventions.GetMessageHashKey(_queueName, message.Id); var tasks = new Task[] { _db.StringSetAsync(RedisQueueConventions.GetMessageExpirationKey(_queueName, message.Id), DateTimeOffset.Now.ToUnixTimeMilliseconds()), _db.HashIncrementAsync(hashKey, RedisHashKeys.DeliveryCount, 1), }; await Task.WhenAll(tasks).ConfigureAwait(false); var hash = await _db.HashGetAllAsync(hashKey).ConfigureAwait(false); return(new RedisMessage <T>(listItem, message, hash, _queueName)); } catch (RedisTimeoutException e) { _hostConfiguration.Log.Error(e, "Error retrieving redis message"); return(null); } catch (RedisException e) { _hostConfiguration.Log.Error(e, "Error retrieving redis message"); return(null); } }
public RedisMessage(RedisValue redisValue, string id, T message, HashEntry[] hashEntries, string queueName) { RedisValue = redisValue; HashKey = RedisQueueConventions.GetMessageHashKey(queueName, id); ExpirationKey = RedisQueueConventions.GetMessageExpirationKey(queueName, id); Message = message; HashEntries = hashEntries.ToStringDictionary(); }
internal Task DeleteDeadletterAsync(RedisDeadletter <T> deadletter) { var deadletterQueueName = RedisQueueConventions.GetDeadLetterQueueName(_queueName); var hash = RedisQueueConventions.GetMessageHashKey(_queueName, deadletter.Message.Id); var expirationKey = RedisQueueConventions.GetMessageExpirationKey(_queueName, deadletter.Message.Id); return(Task.WhenAll(_db.KeyDeleteAsync(new RedisKey[] { hash, expirationKey }), _db.ListRemoveAsync(deadletterQueueName, _serializer.Serialize(deadletter.Message), -1))); }
private async Task <RedisMessage <T> > GetMessageAsync(CancellationTokenSource cancellationsSource) { if (cancellationsSource.IsCancellationRequested) { return(null); } try { byte[] listItem = await _db.ListRightPopLeftPushAsync(_queueName, RedisQueueConventions.GetProcessingQueueName(_queueName)).ConfigureAwait(false); if (listItem == null) { cancellationsSource.Cancel(); return(null); } var message = _serializer.Deserialize <RedisListItem <T> >(listItem.AsSpan()); var hashKey = RedisQueueConventions.GetMessageHashKey(_queueName, message.Id); var tasks = new Task[] { _db.StringSetAsync(RedisQueueConventions.GetMessageExpirationKey(_queueName, message.Id), DateTimeOffset.Now.ToUnixTimeMilliseconds()), _db.HashIncrementAsync(hashKey, RedisHashKeys.DeliveryCount) }; await Task.WhenAll(tasks).ConfigureAwait(false); var hash = await _db.HashGetAllAsync(hashKey).ConfigureAwait(false); return(new RedisMessage <T>(listItem, message.Id, message.Body, hash, _queueName)); } catch (RedisTimeoutException e) { _log.Error(e, "Error retrieving redis message"); return(null); } catch (RedisException e) { _log.Error(e, "Error retrieving redis message"); return(null); } }
private async Task <(bool lost, RedisListItem <T> message, RedisValue listItem)> HandlePotentiallyLostMessage(string queueName, byte[] listItem) { var message = _serializer.Deserialize <RedisListItem <T> >(listItem.AsSpan()); var lastProcessedKey = RedisQueueConventions.GetMessageExpirationKey(queueName, message.Id); var hash = await _db.StringGetAsync(lastProcessedKey).ConfigureAwait(false); if (!hash.IsNull) { var processTimeStamp = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(hash)); if (processTimeStamp + _messageTimeout < DateTimeOffset.Now) { //Message is lost or has exceeded maximum processing time return(true, message, listItem); } } else { await _db.StringSetAsync(lastProcessedKey, DateTimeOffset.Now.Add(-_messageTimeout).ToUnixTimeMilliseconds(), GetDelay() + GetDelay()).ConfigureAwait(false); } return(false, default, listItem);
internal async Task RequeueDeadletterAsync() { var deadLetterQueueName = RedisQueueConventions.GetDeadLetterQueueName(_queueName); var deadLetterProcessingQueueName = RedisQueueConventions.GetProcessingQueueName(deadLetterQueueName); byte[] listItem = await _db.ListRightPopLeftPushAsync(deadLetterQueueName, deadLetterProcessingQueueName).ConfigureAwait(false); if (listItem == null) { return; } var message = _serializer.Deserialize <RedisListItem <T> >(listItem.AsSpan()); var hashKey = RedisQueueConventions.GetMessageHashKey(_queueName, message.Id); var expirationKey = RedisQueueConventions.GetMessageExpirationKey(_queueName, message.Id); await _db.HashDeleteAsync(hashKey, new RedisValue[] { expirationKey, RedisHashKeys.DeliveryCount }).ConfigureAwait(false); await _db.ListRightPopLeftPushAsync(deadLetterProcessingQueueName, _queueName).ConfigureAwait(false); await _db.PublishAsync(_queueName, 0, CommandFlags.FireAndForget).ConfigureAwait(false); }