mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 09:13:02 +08:00
implemented delayed message acknowledgement
This commit is contained in:
@@ -630,25 +630,28 @@ namespace MQTTnet.Client
|
||||
}
|
||||
|
||||
var publishPacket = publishPacketDequeueResult.Item;
|
||||
var publishResult = await HandleReceivedApplicationMessageAsync(publishPacket);
|
||||
|
||||
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false);
|
||||
// no response required
|
||||
}
|
||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
||||
{
|
||||
if (await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false))
|
||||
if (publishResult.ProcessingSucceeded)
|
||||
{
|
||||
await SendAsync(new MqttPubAckPacket
|
||||
var pubAckPacket = new MqttPubAckPacket
|
||||
{
|
||||
PacketIdentifier = publishPacket.PacketIdentifier,
|
||||
ReasonCode = MqttPubAckReasonCode.Success
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
};
|
||||
|
||||
await PublishResponseForReceivedPublishPacket(publishResult, pubAckPacket, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
||||
{
|
||||
if (await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false))
|
||||
if (publishResult.ProcessingSucceeded)
|
||||
{
|
||||
var pubRecPacket = new MqttPubRecPacket
|
||||
{
|
||||
@@ -656,7 +659,7 @@ namespace MQTTnet.Client
|
||||
ReasonCode = MqttPubRecReasonCode.Success
|
||||
};
|
||||
|
||||
await SendAsync(pubRecPacket, cancellationToken).ConfigureAwait(false);
|
||||
await PublishResponseForReceivedPublishPacket(publishResult, pubRecPacket, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -674,6 +677,31 @@ namespace MQTTnet.Client
|
||||
}
|
||||
}
|
||||
|
||||
async Task PublishResponseForReceivedPublishPacket(ReceivedApplicationMessageResult publishResult, MqttBasePacket resultPacket, CancellationToken cancellationToken)
|
||||
{
|
||||
if (publishResult.PendingTask == null)
|
||||
{
|
||||
await SendAsync(resultPacket, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = publishResult.PendingTask.ContinueWith(async x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x.Result) await SendAsync(resultPacket, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling application message.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Task ProcessReceivedPubRecPacket(MqttPubRecPacket pubRecPacket, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_packetDispatcher.TryDispatch(pubRecPacket))
|
||||
@@ -756,7 +784,19 @@ namespace MQTTnet.Client
|
||||
return _adapter.PacketFormatterAdapter.DataConverter.CreatePublishResult(pubRecPacket, pubCompPacket);
|
||||
}
|
||||
|
||||
async Task<bool> HandleReceivedApplicationMessageAsync(MqttPublishPacket publishPacket)
|
||||
struct ReceivedApplicationMessageResult
|
||||
{
|
||||
public readonly bool ProcessingSucceeded;
|
||||
public readonly Task<bool> PendingTask;
|
||||
|
||||
public ReceivedApplicationMessageResult(bool processingSucceeded, Task<bool> pendingTask)
|
||||
{
|
||||
this.ProcessingSucceeded = processingSucceeded;
|
||||
this.PendingTask = pendingTask;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<ReceivedApplicationMessageResult> HandleReceivedApplicationMessageAsync(MqttPublishPacket publishPacket)
|
||||
{
|
||||
var applicationMessage = _adapter.PacketFormatterAdapter.DataConverter.CreateApplicationMessage(publishPacket);
|
||||
|
||||
@@ -765,10 +805,10 @@ namespace MQTTnet.Client
|
||||
{
|
||||
var eventArgs = new MqttApplicationMessageReceivedEventArgs(Options.ClientId, applicationMessage);
|
||||
await handler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
|
||||
return !eventArgs.ProcessingFailed;
|
||||
return new ReceivedApplicationMessageResult(!eventArgs.ProcessingFailed, eventArgs.PendingTask);
|
||||
}
|
||||
|
||||
return true;
|
||||
return new ReceivedApplicationMessageResult(true, null);
|
||||
}
|
||||
|
||||
async Task WaitForTaskAsync(Task task, Task sender)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
@@ -15,5 +16,7 @@ namespace MQTTnet
|
||||
public MqttApplicationMessage ApplicationMessage { get; }
|
||||
|
||||
public bool ProcessingFailed { get; set; }
|
||||
|
||||
public Task<bool> PendingTask { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user