mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-07-02 10:38:16 +00:00
Merge pull request #1353 from PepperDash/mc-subscription-concurrency
fix: make subscriber functionality thread-safe
This commit is contained in:
commit
11d62aebe1
1 changed files with 31 additions and 10 deletions
|
|
@ -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 });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue