-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathBroadcaster.cs
More file actions
57 lines (50 loc) · 1.57 KB
/
Copy pathBroadcaster.cs
File metadata and controls
57 lines (50 loc) · 1.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System.Collections.Concurrent;
using System.Threading.Channels;
namespace NpgsqlRest;
public class Broadcaster<T>
{
private readonly ConcurrentDictionary<Guid, Channel<T>> _channels = new();
public void Broadcast(T message)
{
foreach (var kvp in _channels)
{
var writer = kvp.Value.Writer;
if (!writer.TryWrite(message))
{
// Channel is closed, remove it
_channels.TryRemove(kvp.Key, out _);
}
}
}
public ChannelReader<T> Subscribe(Guid subscriberId)
{
if (_channels.TryRemove(subscriberId, out var existingChannel))
{
existingChannel.Writer.TryComplete();
}
var channel = Channel.CreateUnbounded<T>();
_channels[subscriberId] = channel;
return channel.Reader;
}
public void Unsubscribe(Guid subscriberId)
{
if (_channels.TryRemove(subscriberId, out var channel))
{
channel.Writer.TryComplete();
}
}
public void CompleteAll()
{
foreach (var kvp in _channels)
{
kvp.Value.Writer.TryComplete();
}
_channels.Clear();
}
/// <summary>
/// Number of currently subscribed channels. Used by integration tests to wait until an SSE
/// subscriber has registered before triggering a publish, avoiding a race between
/// <c>Subscribe</c> and the test's HTTP call. Cheap on a <see cref="ConcurrentDictionary{TKey,TValue}"/>.
/// </summary>
public int SubscriberCount => _channels.Count;
}