Skip to content

Commit 22d23eb

Browse files
authored
Subscribe: Better transaction management (#169)
1 parent 4cc7e20 commit 22d23eb

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

Source/HiveMQtt/Client/Options/HiveMQClientOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,10 @@ public void Validate()
285285
{
286286
this.GenerateClientID();
287287
}
288-
else if (this.ClientId.Length > 23)
288+
289+
if (this.ClientId.Length > 23)
289290
{
290-
// FIXME: Warn on exceeded length; can use but it may not work...
291+
Logger.Info($"Client ID {this.ClientId} is longer than 23 characters. This may cause issues with some brokers.");
291292
}
292293
}
293294

Source/HiveMQtt/MQTT5/Packets/SubscribePacket.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
namespace HiveMQtt.MQTT5.Packets;
1717

1818
using System.IO;
19-
19+
using HiveMQtt.Client.Events;
2020
using HiveMQtt.Client.Options;
2121
using HiveMQtt.MQTT5.Types;
2222

@@ -43,6 +43,14 @@ public SubscribePacket(SubscribeOptions options, ushort packetIdentifier, Dictio
4343
{
4444
this.Properties.UserProperties = userProperties;
4545
}
46+
47+
// Setup the TaskCompletionSource so users can simply call
48+
//
49+
// await SubscribePacket.OnCompleteTCS
50+
//
51+
// to wait for the subscribe transaction to complete.
52+
this.OnComplete += (sender, args) => this.OnCompleteTCS.SetResult(args.SubAckPacket);
53+
4654
}
4755

4856
/// <summary>
@@ -53,6 +61,46 @@ public SubscribePacket(SubscribeOptions options, ushort packetIdentifier, Dictio
5361
/// <inheritdoc/>
5462
public override ControlPacketType ControlPacketType => ControlPacketType.Subscribe;
5563

64+
65+
/// <summary>
66+
/// Valid for outgoing Subscribe packets. An event that is fired after the the subscribe transaction is complete.
67+
/// </summary>
68+
public event EventHandler<OnSubAckReceivedEventArgs> OnComplete = new((client, e) => { });
69+
70+
internal virtual void OnCompleteEventLauncher(SubAckPacket packet)
71+
{
72+
if (this.OnComplete != null && this.OnComplete.GetInvocationList().Length > 0)
73+
{
74+
var eventArgs = new OnSubAckReceivedEventArgs(packet);
75+
Logger.Trace("SubscribePacket.OnCompleteEventLauncher");
76+
_ = Task.Run(() => this.OnComplete?.Invoke(this, eventArgs)).ContinueWith(
77+
t =>
78+
{
79+
if (t.IsFaulted)
80+
{
81+
if (t.Exception is not null)
82+
{
83+
Logger.Error("SubscribePacket.OnCompleteEventLauncher exception: " + t.Exception.Message);
84+
foreach (var ex in t.Exception.InnerExceptions)
85+
{
86+
Logger.Error("SubscribePacket.OnCompleteEventLauncher inner exception: " + ex.Message);
87+
}
88+
}
89+
}
90+
},
91+
TaskScheduler.Default);
92+
}
93+
}
94+
95+
/// <summary>
96+
/// Gets the awaitable TaskCompletionSource for the subscribe transaction.
97+
/// <para>
98+
/// Valid for outgoing subscribe packets. A TaskCompletionSource that is set when the subscribe transaction is complete.
99+
/// </para>
100+
/// </summary>
101+
public TaskCompletionSource<SubAckPacket> OnCompleteTCS { get; } = new();
102+
103+
56104
/// <summary>
57105
/// Encode this packet to be sent on the wire.
58106
/// </summary>

0 commit comments

Comments
 (0)