mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-15 12:44:58 +00:00
Merge pull request #1353 from PepperDash/mc-subscription-concurrency
fix: make subscriber functionality thread-safe
This commit is contained in:
@@ -31,7 +31,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Unsoliciited feedback from a device in a messenger will ONLY be sent to devices in this subscription list. When a client disconnects, it's ID will be removed from the collection.
|
/// Unsoliciited feedback from a device in a messenger will ONLY be sent to devices in this subscription list. When a client disconnects, it's ID will be removed from the collection.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected HashSet<string> SubscriberIds = new HashSet<string>();
|
private readonly HashSet<string> subscriberIds = new HashSet<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock object for thread-safe access to SubscriberIds
|
||||||
|
/// </summary>
|
||||||
|
private readonly object _subscriberLock = new object();
|
||||||
|
|
||||||
private readonly List<string> _deviceInterfaces;
|
private readonly List<string> _deviceInterfaces;
|
||||||
|
|
||||||
@@ -193,14 +198,15 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SubscriberIds.Any(id => id == clientId))
|
lock (_subscriberLock)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Client {clientId} already subscribed", clientId);
|
if (!subscriberIds.Add(clientId))
|
||||||
return;
|
{
|
||||||
|
this.LogVerbose("Client {clientId} already subscribed", clientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SubscriberIds.Add(clientId);
|
|
||||||
|
|
||||||
this.LogDebug("Client {clientId} subscribed", clientId);
|
this.LogDebug("Client {clientId} subscribed", clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,14 +222,22 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SubscriberIds.Any(i => i == clientId))
|
bool wasSubscribed;
|
||||||
|
lock (_subscriberLock)
|
||||||
|
{
|
||||||
|
wasSubscribed = subscriberIds.Contains(clientId);
|
||||||
|
if (wasSubscribed)
|
||||||
|
{
|
||||||
|
subscriberIds.Remove(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasSubscribed)
|
||||||
{
|
{
|
||||||
this.LogVerbose("Client with ID {clientId} is not subscribed", clientId);
|
this.LogVerbose("Client with ID {clientId} is not subscribed", clientId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubscriberIds.RemoveWhere((i) => i == clientId);
|
|
||||||
|
|
||||||
this.LogInformation("Client with ID {clientId} unsubscribed", clientId);
|
this.LogInformation("Client with ID {clientId} unsubscribed", clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +326,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
// If client is null or empty, this message is unsolicited feedback. Iterate through the subscriber list and send to all interested parties
|
// If client is null or empty, this message is unsolicited feedback. Iterate through the subscriber list and send to all interested parties
|
||||||
if (string.IsNullOrEmpty(clientId))
|
if (string.IsNullOrEmpty(clientId))
|
||||||
{
|
{
|
||||||
foreach (var client in SubscriberIds)
|
// Create a snapshot of subscribers to avoid collection modification during iteration
|
||||||
|
List<string> subscriberSnapshot;
|
||||||
|
lock (_subscriberLock)
|
||||||
|
{
|
||||||
|
subscriberSnapshot = new List<string>(subscriberIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var client in subscriberSnapshot)
|
||||||
{
|
{
|
||||||
AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = client, Content = content });
|
AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = client, Content = content });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user