2
2
3
3
namespace NNostr . Client ;
4
4
5
-
6
5
public class NostrClientPool : IDisposable
7
6
{
8
7
private readonly ConcurrentDictionary < string , NostrClientWrapper > _clientPool = new ( ) ;
9
8
10
- private readonly Timer _cleanupTimer ;
9
+ private Timer ? _cleanupTimer ;
10
+ private readonly TimeSpan _unusedClientTimeout ;
11
11
12
12
public NostrClientPool ( TimeSpan ? unusedClientTimeout = null )
13
13
{
14
- unusedClientTimeout ??= TimeSpan . FromMinutes ( 5 ) ;
15
- _cleanupTimer = new Timer ( CleanupExpiredClients , null , unusedClientTimeout . Value , unusedClientTimeout . Value ) ;
14
+ _unusedClientTimeout = unusedClientTimeout ?? TimeSpan . FromMinutes ( 5 ) ;
15
+ InitBackgroundTask ( ) ;
16
+ }
17
+
18
+ protected virtual void InitBackgroundTask ( )
19
+ {
20
+ _cleanupTimer ? . Dispose ( ) ;
21
+ _cleanupTimer = new Timer ( CleanupExpiredClients , null , _unusedClientTimeout , _unusedClientTimeout ) ;
16
22
}
17
23
18
24
public ( INostrClient , IDisposable ) GetClient ( Uri [ ] relays )
19
25
{
20
- if ( relays . Length == 0 )
26
+ if ( relays . Length == 0 )
21
27
throw new ArgumentException ( "At least one relay is required" , nameof ( relays ) ) ;
22
-
28
+
23
29
var connString = GetConnString ( relays ) ;
24
30
25
31
var clientWrapper = _clientPool . GetOrAdd ( connString ,
26
- k => new NostrClientWrapper ( relays . Length > 1 ? new CompositeNostrClient ( relays ) : new NostrClient ( relays [ 0 ] ) ) ) ;
32
+ k => new NostrClientWrapper ( relays . Length > 1
33
+ ? new CompositeNostrClient ( relays )
34
+ : new NostrClient ( relays [ 0 ] ) ) ) ;
27
35
28
36
clientWrapper . IncrementUsage ( ) ;
29
37
@@ -33,12 +41,19 @@ public NostrClientPool(TimeSpan? unusedClientTimeout = null)
33
41
public async Task < ( INostrClient , IDisposable ) > GetClientAndConnect ( Uri [ ] relays , CancellationToken token )
34
42
{
35
43
var result = GetClient ( relays ) ;
36
-
37
- await result . Item1 . ConnectAndWaitUntilConnected ( token , CancellationToken . None ) ;
38
-
39
- return result ;
44
+ try
45
+ {
46
+ await result . Item1 . ConnectAndWaitUntilConnected ( token , CancellationToken . None ) ;
47
+ return result ;
48
+ }
49
+ catch ( Exception e )
50
+ {
51
+ result . Item2 . Dispose ( ) ;
52
+ KillClient ( relays ) ;
53
+ throw ;
54
+ }
40
55
}
41
-
56
+
42
57
private string GetConnString ( Uri [ ] relays )
43
58
{
44
59
return string . Join ( ';' , relays . Select ( r => r . ToString ( ) ) ) ;
@@ -67,24 +82,24 @@ public void CleanupExpiredClients(object? state)
67
82
}
68
83
}
69
84
70
- private class UsageDisposable : IDisposable
85
+ internal class UsageDisposable : IDisposable
71
86
{
72
- private readonly NostrClientWrapper _clientWrapper ;
87
+ internal readonly NostrClientWrapper ClientWrapper ;
73
88
74
89
public UsageDisposable ( NostrClientWrapper clientWrapper )
75
90
{
76
- _clientWrapper = clientWrapper ;
91
+ ClientWrapper = clientWrapper ;
77
92
}
78
93
79
94
public void Dispose ( )
80
95
{
81
- _clientWrapper . DecrementUsage ( ) ;
96
+ ClientWrapper . DecrementUsage ( ) ;
82
97
}
83
98
}
84
99
85
100
public void Dispose ( )
86
101
{
87
- _cleanupTimer . Dispose ( ) ;
102
+ _cleanupTimer ? . Dispose ( ) ;
88
103
foreach ( var client in _clientPool . Values )
89
104
{
90
105
client . Dispose ( ) ;
0 commit comments