Skip to content

Commit 45dee38

Browse files
committed
Bump
1 parent e0ba467 commit 45dee38

File tree

4 files changed

+64
-22
lines changed

4 files changed

+64
-22
lines changed

NNostr.Client/NNostr.Client.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<Nullable>enable</Nullable>
77
<LangVersion>latest</LangVersion>
88
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
9-
<PackageVersion>0.0.53</PackageVersion>
9+
<PackageVersion>0.0.54</PackageVersion>
1010
<Title>Nostr Client</Title>
1111
<Description>A client for Nostr</Description>
1212
<Copyright>MIT</Copyright>
@@ -18,7 +18,7 @@
1818
</PropertyGroup>
1919

2020
<ItemGroup>
21-
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.1.1">
21+
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.2.25">
2222
<PrivateAssets>all</PrivateAssets>
2323
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2424
</PackageReference>

NNostr.Client/NostrClientPool.cs

+32-17
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,36 @@
22

33
namespace NNostr.Client;
44

5-
65
public class NostrClientPool : IDisposable
76
{
87
private readonly ConcurrentDictionary<string, NostrClientWrapper> _clientPool = new();
98

10-
private readonly Timer _cleanupTimer;
9+
private Timer? _cleanupTimer;
10+
private readonly TimeSpan _unusedClientTimeout;
1111

1212
public NostrClientPool(TimeSpan? unusedClientTimeout = null)
1313
{
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);
1622
}
1723

1824
public (INostrClient, IDisposable) GetClient(Uri[] relays)
1925
{
20-
if(relays.Length == 0)
26+
if (relays.Length == 0)
2127
throw new ArgumentException("At least one relay is required", nameof(relays));
22-
28+
2329
var connString = GetConnString(relays);
2430

2531
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])));
2735

2836
clientWrapper.IncrementUsage();
2937

@@ -33,12 +41,19 @@ public NostrClientPool(TimeSpan? unusedClientTimeout = null)
3341
public async Task<(INostrClient, IDisposable)> GetClientAndConnect(Uri[] relays, CancellationToken token)
3442
{
3543
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+
}
4055
}
41-
56+
4257
private string GetConnString(Uri[] relays)
4358
{
4459
return string.Join(';', relays.Select(r => r.ToString()));
@@ -67,24 +82,24 @@ public void CleanupExpiredClients(object? state)
6782
}
6883
}
6984

70-
private class UsageDisposable : IDisposable
85+
internal class UsageDisposable : IDisposable
7186
{
72-
private readonly NostrClientWrapper _clientWrapper;
87+
internal readonly NostrClientWrapper ClientWrapper;
7388

7489
public UsageDisposable(NostrClientWrapper clientWrapper)
7590
{
76-
_clientWrapper = clientWrapper;
91+
ClientWrapper = clientWrapper;
7792
}
7893

7994
public void Dispose()
8095
{
81-
_clientWrapper.DecrementUsage();
96+
ClientWrapper.DecrementUsage();
8297
}
8398
}
8499

85100
public void Dispose()
86101
{
87-
_cleanupTimer.Dispose();
102+
_cleanupTimer?.Dispose();
88103
foreach (var client in _clientPool.Values)
89104
{
90105
client.Dispose();

NNostr.Client/NostrClientWrapper.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public class NostrClientWrapper : IDisposable
44
{
55
public INostrClient Client { get; private set; }
6-
private int _usageCount = 0;
6+
internal int UsageCount = 0;
77
private bool _isDisposed = false;
88
private DateTimeOffset _lastUsed;
99

@@ -16,13 +16,13 @@ public NostrClientWrapper(INostrClient client)
1616
public void IncrementUsage()
1717
{
1818
_lastUsed = DateTimeOffset.UtcNow;
19-
Interlocked.Increment(ref _usageCount);
19+
Interlocked.Increment(ref UsageCount);
2020
}
2121

2222
public void DecrementUsage()
2323
{
2424
_lastUsed = DateTimeOffset.UtcNow;
25-
if (Interlocked.Decrement(ref _usageCount) == 0 && IsExpired())
25+
if (Interlocked.Decrement(ref UsageCount) == 0 && IsExpired())
2626
{
2727
Dispose();
2828
}

NNostr.Tests/ClientTests.cs

+27
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,33 @@ public NostrWalletCOnnectTests()
1919

2020
}
2121

22+
23+
[Fact]
24+
public async Task RsspectCancelltaion()
25+
{
26+
var broken =
27+
"nostr+walletconnect://142cc22d6c00258709ae2b5312c54d40420b0aa495839ce5f13ae0025f1263db?relay=wss://relay.getalby.com/v1&secret=e06cffe97a30701d309d8c041ef67e2b37f1524c128ce594501f21cd723350d8";
28+
29+
var result = NIP47.ParseUri(new Uri(broken));
30+
31+
var pool = new NostrClientPool();
32+
33+
var cts = new CancellationTokenSource();
34+
var connectionResult = pool.GetClientAndConnect(result.relays, cts.Token);
35+
36+
var res = await connectionResult;
37+
Assert.Equal(1, Assert.IsType<NostrClientPool.UsageDisposable>(res.Item2).ClientWrapper.UsageCount);
38+
39+
var connectionResult2 = await pool.GetClientAndConnect(result.relays, cts.Token);
40+
41+
Assert.Equal(2, Assert.IsType<NostrClientPool.UsageDisposable>(connectionResult2.Item2).ClientWrapper.UsageCount);
42+
Assert.Equal(res.Item1, connectionResult2.Item1);
43+
44+
45+
46+
}
47+
48+
2249
// [Fact]
2350
public async Task CanParseUri()
2451
{

0 commit comments

Comments
 (0)