可靠redis队列里的高级用法中消息体和消息键好像不是可靠消息
ZevFung opened this issue · comments
Zev_Fung commented
/// <summary>高级消费消息。消息处理成功后,自动确认并删除消息体</summary>
/// <remarks>
/// Publish 必须跟 ConsumeAsync 配对使用。
/// </remarks>
/// <param name="func"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public async Task<TResult> ConsumeAsync<TResult>(Func<T, Task<TResult>> func, Int32 timeout = 0)
{
RetryAck();
// 取出消息键
var msgId = timeout < 0 ?
await ExecuteAsync((rc, k) => rc.ExecuteAsync<String>("RPOPLPUSH", Key, AckKey), true) :
await ExecuteAsync((rc, k) => rc.ExecuteAsync<String>("BRPOPLPUSH", Key, AckKey, timeout), true);
if (msgId.IsNullOrEmpty()) return default;
_Status.Consumes++;
// 取出消息。如果重复消费,或者业务层已经删除消息,此时将拿不到
if (!Redis.TryGetValue(msgId, out T messge))
{
// 拿不到消息体,直接确认消息键
Acknowledge(msgId);
return default;
}
// 处理消息。如果消息已被删除,此时调用func将受到空引用
var rs = await func(messge);
// 确认并删除消息
Redis.Remove(msgId);
Acknowledge(msgId);
return rs;
}
func执行是否成功,都会调用Redis.Remove(msgId);和Acknowledge(msgId);,消息都会自动删除和确认。这里我觉得func不成功,就不调用Redis.Remove(msgId);和Acknowledge(msgId);
Stone commented
func是否执行成功,是以抛出异常为准。只要没有抛出异常,就认为执行成功,需要确认消息
Zev_Fung commented
谢谢