Skip to content

Commit b717826

Browse files
authored
Merge pull request #220 from madelson/release-2.5
Release 2.5
2 parents e5b0096 + 91262f7 commit b717826

35 files changed

+625
-385
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ Contributions are welcome! If you are interested in contributing towards a new o
141141
Setup steps for working with the repository locally are documented [here](docs/Developing%20DistributedLock.md).
142142

143143
## Release notes
144+
- 2.5
145+
- Add support for creating Postgres locks off `DbDataSource` which is helpful for apps using `NpgsqlMultiHostDataSource`. Thanks @davidngjy for implementing! ([#153](https://github.com/madelson/DistributedLock/issues/153), DistributedLock.Postgres 1.2.0)
146+
- Upgrade Npgsql to 8.0.3 to avoid vulnerability. Thanks @Meir017/@davidngjy for implementing! ([#218](https://github.com/madelson/DistributedLock/issues/218), DistributedLock.Postgres 1.2.0)
147+
- Fix Postgres race condition with connection keepalive enabled ([#216](https://github.com/madelson/DistributedLock/issues/216), DistributedLock.Core 1.0.7)
148+
- Upgrade Microsoft.Data.SqlClient to 5.2.1 to avoid vulnerability ([#210](https://github.com/madelson/DistributedLock/issues/210), DistributedLock.SqlServer 1.0.5)
144149
- 2.4
145150
- Add support for transaction-scoped locking in Postgres using `pg_advisory_xact_lock` which is helpful when using PgBouncer ([#168](https://github.com/madelson/DistributedLock/issues/168), DistributedLock.Postgres 1.1.0)
146151
- Improve support for newer versions of StackExchange.Redis, especially when using the default backlog policy ([#162](https://github.com/madelson/DistributedLock/issues/162), DistributedLock.Redis 1.0.3). Thanks [@Bartleby2718](https://github.com/Bartleby2718) for helping with this!

docs/DistributedLock.Postgres.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Under the hood, [Postgres advisory locks can be based on either one 64-bit integ
2828
- Passing an ASCII string with 0-9 characters, which will be mapped to a `long` based on a custom scheme.
2929
- Passing an arbitrary string with the `allowHashing` option set to `true` which will be hashed to a `long`. Note that hashing will only be used if other methods of interpreting the string fail.
3030

31-
In addition to specifying the `key`, Postgres-based locks allow you to specify either a `connectionString` or an `IDbConnection` as a means of connecting to the database. In most cases, using a `connectionString` is preferred because it allows for the library to efficiently multiplex connections under the hood and eliminates the risk that the passed-in `IDbConnection` gets used in a way that disrupts the locking process. **NOTE that since `IDbConnection` objects are not thread-safe, lock objects constructed with them can only be used by one thread at a time.**
31+
In addition to specifying the `key`, Postgres-based locks allow you to specify either a `connectionString`, an `IDbConnection`, or a `DbDataSource` as a means of connecting to the database. In most cases, using a `connectionString` is preferred because it allows for the library to efficiently multiplex connections under the hood and, in the case of `IDbConnection`, eliminates the risk that the passed-in `IDbConnection` gets used in a way that disrupts the locking process. **NOTE that since `IDbConnection` objects are not thread-safe, lock objects constructed with them can only be used by one thread at a time.**
3232

3333
## Options
3434

src/Directory.Packages.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
<PackageVersion Include="NUnit.Analyzers" Version="4.1.0" />
1313
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="3.21.130" Condition="'$(TargetFramework)' == 'netstandard2.1'" />
1414
<PackageVersion Include="Oracle.ManagedDataAccess" Version="21.13.0" Condition="'$(TargetFramework)' == 'net462'" />
15-
<PackageVersion Include="Npgsql" Version="8.0.2" />
15+
<PackageVersion Include="Npgsql" Version="8.0.3" />
1616
<PackageVersion Include="StackExchange.Redis" Version="2.7.27" />
17-
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.0" />
17+
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.1" />
1818
<PackageVersion Include="nunit" Version="3.14.0" />
1919
<PackageVersion Include="nunit3testadapter" Version="4.5.0" />
2020
<PackageVersion Include="Microsoft.NET.Test.SDK" Version="17.9.0" />
@@ -27,4 +27,4 @@
2727
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'net462'" />
2828
<PackageVersion Include="System.ValueTuple" Version="4.5.0" Condition="'$(TargetFramework)' == 'net462'" />
2929
</ItemGroup>
30-
</Project>
30+
</Project>

src/DistributedLock.Core/DistributedLock.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</PropertyGroup>
1212

1313
<PropertyGroup>
14-
<Version>1.0.6</Version>
14+
<Version>1.0.7</Version>
1515
<AssemblyVersion>1.0.0.0</AssemblyVersion>
1616
<Authors>Michael Adelson</Authors>
1717
<Description>Core interfaces and utilities that support the DistributedLock.* family of packages</Description>

src/DistributedLock.Core/Internal/AsyncLock.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,9 @@ public async ValueTask<IDisposable> AcquireAsync(CancellationToken cancellationT
3131
return acquired ? new Handle(this._semaphore) : null;
3232
}
3333

34-
private sealed class Handle : IDisposable
34+
private sealed class Handle(SemaphoreSlim semaphore) : IDisposable
3535
{
36-
private SemaphoreSlim? _semaphore;
37-
38-
public Handle(SemaphoreSlim semaphore)
39-
{
40-
this._semaphore = semaphore;
41-
}
36+
private SemaphoreSlim? _semaphore = semaphore;
4237

4338
public void Dispose() => Interlocked.Exchange(ref this._semaphore, null)?.Release();
4439
}

src/DistributedLock.Core/Internal/Data/ConnectionMonitor.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public IDatabaseConnectionMonitoringHandle GetMonitoringHandle()
138138

139139
var connectionLostTokenSource = new CancellationTokenSource();
140140
var handle = new MonitoringHandle(this, connectionLostTokenSource.Token);
141-
(this._monitoringHandleRegistrations ??= new Dictionary<MonitoringHandle, CancellationTokenSource>())
141+
(this._monitoringHandleRegistrations ??= [])
142142
.Add(handle, connectionLostTokenSource);
143143

144144
if (!this.StartMonitorWorkerIfNeededNoLock()
@@ -403,16 +403,10 @@ private async Task<bool> DoKeepaliveAsync(TimeoutValue keepaliveCadence, Cancell
403403
return true;
404404
}
405405

406-
private sealed class MonitoringHandle : IDatabaseConnectionMonitoringHandle
406+
private sealed class MonitoringHandle(ConnectionMonitor keepaliveHelper, CancellationToken cancellationToken) : IDatabaseConnectionMonitoringHandle
407407
{
408-
private ConnectionMonitor? _monitor;
409-
private readonly CancellationToken _connectionLostToken;
410-
411-
public MonitoringHandle(ConnectionMonitor keepaliveHelper, CancellationToken cancellationToken)
412-
{
413-
this._monitor = keepaliveHelper;
414-
this._connectionLostToken = cancellationToken;
415-
}
408+
private ConnectionMonitor? _monitor = keepaliveHelper;
409+
private readonly CancellationToken _connectionLostToken = cancellationToken;
416410

417411
public CancellationToken ConnectionLostToken => Volatile.Read(ref this._monitor) != null ? this._connectionLostToken : throw new ObjectDisposedException("handle");
418412

src/DistributedLock.Core/Internal/Data/DatabaseConnection.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ protected DatabaseConnection(IDbTransaction transaction, bool isExternallyOwned)
4646

4747
public DatabaseCommand CreateCommand()
4848
{
49-
var command = this.InnerConnection.CreateCommand();
49+
IDbCommand command;
50+
// Because of Npgsql's command recycling (https://github.com/npgsql/npgsql/blob/main/src/Npgsql/NpgsqlConnection.cs#L566),
51+
// CreateCommand() is not actually thread-safe. Ideally this would use this.ConnectionMonitor.AcquireConnectionLockAsync
52+
// like other operations, but that requires a change to the Core internal API so I'm leaving it for #217. For the current
53+
// issue with Npgsql, merely synchronizing access to this method should be good enough, and ConnectionMonitor makes a
54+
// fine lock object that isn't being used elsewhere (#216)
55+
lock (this.ConnectionMonitor) { command = this.InnerConnection.CreateCommand(); }
5056
command.Transaction = this._transaction;
5157
return new DatabaseCommand(command, this);
5258
}

src/DistributedLock.Core/Internal/ManagedFinalizerQueue.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private Task FinalizeAsync(bool waitForItemFinalization)
142142
var itemFinalizerTask = this.TryRemove(kvp.Key, disposeKey: true);
143143
if (waitForItemFinalization)
144144
{
145-
(itemFinalizerTasks ??= new List<Task>()).Add(itemFinalizerTask);
145+
(itemFinalizerTasks ??= []).Add(itemFinalizerTask);
146146
}
147147
}
148148
}
@@ -171,16 +171,10 @@ private Task TryRemove(IAsyncDisposable key, bool disposeKey)
171171
return Task.CompletedTask;
172172
}
173173

174-
private sealed class Registration : IDisposable
174+
private sealed class Registration(ManagedFinalizerQueue queue, IAsyncDisposable key) : IDisposable
175175
{
176-
private readonly ManagedFinalizerQueue _queue;
177-
private IAsyncDisposable? _key;
178-
179-
public Registration(ManagedFinalizerQueue queue, IAsyncDisposable key)
180-
{
181-
this._queue = queue;
182-
this._key = key;
183-
}
176+
private readonly ManagedFinalizerQueue _queue = queue;
177+
private IAsyncDisposable? _key = key;
184178

185179
public void Dispose()
186180
{

src/DistributedLock.Core/packages.lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@
172172
},
173173
"Microsoft.NET.ILLink.Tasks": {
174174
"type": "Direct",
175-
"requested": "[8.0.2, )",
176-
"resolved": "8.0.2",
177-
"contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A=="
175+
"requested": "[8.0.4, )",
176+
"resolved": "8.0.4",
177+
"contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw=="
178178
},
179179
"Microsoft.SourceLink.GitHub": {
180180
"type": "Direct",

src/DistributedLock.Postgres/DistributedLock.Postgres.csproj

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;netstandard2.1;net462</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.0;netstandard2.1;net462;net8.0</TargetFrameworks>
55
<RootNamespace>Medallion.Threading.Postgres</RootNamespace>
66
<GenerateDocumentationFile>True</GenerateDocumentationFile>
77
<WarningLevel>4</WarningLevel>
@@ -11,7 +11,7 @@
1111
</PropertyGroup>
1212

1313
<PropertyGroup>
14-
<Version>1.1.0</Version>
14+
<Version>1.2.0</Version>
1515
<AssemblyVersion>1.0.0.0</AssemblyVersion>
1616
<Authors>Michael Adelson</Authors>
1717
<Description>Provides a distributed lock implementation based on Postgresql</Description>
@@ -44,18 +44,23 @@
4444
<DefineConstants>TRACE;DEBUG</DefineConstants>
4545
</PropertyGroup>
4646

47+
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
48+
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" />
49+
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" />
50+
</ItemGroup>
51+
4752
<ItemGroup>
4853
<PackageReference Include="Npgsql" />
49-
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All"/>
54+
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
5055
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" PrivateAssets="All" />
5156
</ItemGroup>
52-
57+
5358
<ItemGroup>
5459
<ProjectReference Include="..\DistributedLock.Core\DistributedLock.Core.csproj" />
5560
</ItemGroup>
5661

5762
<ItemGroup>
58-
<Using Remove="System.Net.Http"/>
63+
<Using Remove="System.Net.Http" />
5964
</ItemGroup>
6065

6166
<Import Project="..\FixDistributedLockCoreDependencyVersion.targets" />

0 commit comments

Comments
 (0)