implemented delayed message acknowledgement

This commit is contained in:
tamas.kurucsai
2021-01-18 10:47:21 +01:00
parent e1d39a3fef
commit f955b4a3e6
2 changed files with 52 additions and 9 deletions
+49 -9
View File
@@ -630,25 +630,28 @@ namespace MQTTnet.Client
} }
var publishPacket = publishPacketDequeueResult.Item; var publishPacket = publishPacketDequeueResult.Item;
var publishResult = await HandleReceivedApplicationMessageAsync(publishPacket);
if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce) if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{ {
await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false); // no response required
} }
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce) 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, PacketIdentifier = publishPacket.PacketIdentifier,
ReasonCode = MqttPubAckReasonCode.Success ReasonCode = MqttPubAckReasonCode.Success
}, cancellationToken).ConfigureAwait(false); };
await PublishResponseForReceivedPublishPacket(publishResult, pubAckPacket, cancellationToken).ConfigureAwait(false);
} }
} }
else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce) else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
{ {
if (await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false)) if (publishResult.ProcessingSucceeded)
{ {
var pubRecPacket = new MqttPubRecPacket var pubRecPacket = new MqttPubRecPacket
{ {
@@ -656,7 +659,7 @@ namespace MQTTnet.Client
ReasonCode = MqttPubRecReasonCode.Success ReasonCode = MqttPubRecReasonCode.Success
}; };
await SendAsync(pubRecPacket, cancellationToken).ConfigureAwait(false); await PublishResponseForReceivedPublishPacket(publishResult, pubRecPacket, cancellationToken).ConfigureAwait(false);
} }
} }
else 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) Task ProcessReceivedPubRecPacket(MqttPubRecPacket pubRecPacket, CancellationToken cancellationToken)
{ {
if (!_packetDispatcher.TryDispatch(pubRecPacket)) if (!_packetDispatcher.TryDispatch(pubRecPacket))
@@ -756,7 +784,19 @@ namespace MQTTnet.Client
return _adapter.PacketFormatterAdapter.DataConverter.CreatePublishResult(pubRecPacket, pubCompPacket); 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); var applicationMessage = _adapter.PacketFormatterAdapter.DataConverter.CreateApplicationMessage(publishPacket);
@@ -765,10 +805,10 @@ namespace MQTTnet.Client
{ {
var eventArgs = new MqttApplicationMessageReceivedEventArgs(Options.ClientId, applicationMessage); var eventArgs = new MqttApplicationMessageReceivedEventArgs(Options.ClientId, applicationMessage);
await handler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false); 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) async Task WaitForTaskAsync(Task task, Task sender)
@@ -1,4 +1,5 @@
using System; using System;
using System.Threading.Tasks;
namespace MQTTnet namespace MQTTnet
{ {
@@ -15,5 +16,7 @@ namespace MQTTnet
public MqttApplicationMessage ApplicationMessage { get; } public MqttApplicationMessage ApplicationMessage { get; }
public bool ProcessingFailed { get; set; } public bool ProcessingFailed { get; set; }
public Task<bool> PendingTask { get; set; }
} }
} }