Skip to content

Commit 802fad5

Browse files
committed
improve log
1 parent f223dde commit 802fad5

5 files changed

Lines changed: 53 additions & 19 deletions

File tree

.github/workflows/deploy-nuget.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ jobs:
3333
if [ ! -z "$PROJECT_PATH" ]; then
3434
APP=`basename "${PROJECT_PATH}" .csproj`
3535
fi
36-
36+
3737
CHANGE_FILES=`git diff --no-commit-id --name-only HEAD^`
3838
3939
CHANGED=`echo "$CHANGE_FILES" | grep -Em 1 '.cs|.proto' || true`
4040
if [ -z "$CHANGED" ] && [ "${{ inputs.force }}" != true ]; then
4141
echo "No changes detected"
42-
42+
4343
APP=""
4444
fi
45-
45+
4646
echo "app=${APP}" >> $GITHUB_OUTPUT
4747
Build:
4848
needs: Detect
@@ -62,5 +62,5 @@ jobs:
6262
name: Push Package
6363
with:
6464
artifact: ${{ needs.Build.outputs.artifact }}
65-
nuget-api-url: ${{ secrets.NUGET_API_URL }}
65+
nuget-api-url: ${{ vars.NUGET_API_URL }}
6666
nuget-api-key: ${{ secrets.NUGET_API_KEY }}

KeyCountLocker.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
using System.Collections.Concurrent;
2+
using Microsoft.Extensions.Logging;
23

34
namespace Netcorext.Extensions.Threading;
45

5-
public class KeyCountLocker
6+
public class KeyCountLocker : KeyLocker
67
{
78
private readonly long _minimum;
89
private readonly long? _maximum;
910
private static readonly ConcurrentDictionary<string, KeyLockerState<long>> CountLockers = new();
10-
private static readonly KeyLocker Locker = new();
1111

1212
public KeyCountLocker(long minimum = 1, long? maximum = null)
1313
{
1414
_minimum = minimum;
1515
_maximum = maximum;
1616
}
1717

18+
public KeyCountLocker(long minimum = 1, long? maximum = null, long deadLockTimes = DEFAULT_DEAD_LOCK_TIMES, ILogger? logger = null) : base(deadLockTimes, logger)
19+
{
20+
_minimum = minimum;
21+
_maximum = maximum;
22+
}
23+
1824
public async Task<bool> IncrementAsync(string key, CancellationToken cancellationToken = default)
1925
{
2026
var newLocker = new KeyLockerState<long>
@@ -23,33 +29,33 @@ public async Task<bool> IncrementAsync(string key, CancellationToken cancellatio
2329
};
2430
try
2531
{
26-
await Locker.WaitAsync(key, cancellationToken);
32+
await WaitAsync(key, cancellationToken);
2733

2834
if (!CountLockers.TryGetValue(key, out var oldLocker))
2935
return CountLockers.TryAdd(key, newLocker);
3036

3137
if (oldLocker.State + 1 > _maximum)
3238
return false;
33-
39+
3440
newLocker.State = oldLocker.State + 1;
35-
41+
3642
return CountLockers.TryUpdate(key, newLocker, oldLocker);
3743
}
3844
finally
3945
{
40-
Locker.Release(key);
46+
Release(key);
4147
}
4248
}
4349

4450
public async Task<bool> DecrementAsync(string key, CancellationToken cancellationToken = default)
4551
{
4652
try
4753
{
48-
await Locker.WaitAsync(key, cancellationToken);
54+
await WaitAsync(key, cancellationToken);
4955

5056
if (!CountLockers.TryGetValue(key, out var oldLocker))
5157
return true;
52-
58+
5359
var newLocker = new KeyLockerState<long>
5460
{
5561
State = oldLocker.State - 1
@@ -62,7 +68,7 @@ public async Task<bool> DecrementAsync(string key, CancellationToken cancellatio
6268
}
6369
finally
6470
{
65-
Locker.Release(key);
71+
Release(key);
6672
}
6773
}
6874

@@ -73,4 +79,4 @@ public Task<long> GetAsync(string key, CancellationToken cancellationToken = def
7379

7480
return Task.FromResult(locker.State);
7581
}
76-
}
82+
}

KeyLocker.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
using System.Collections.Concurrent;
2+
using System.Diagnostics;
3+
using Microsoft.Extensions.Logging;
24

35
namespace Netcorext.Extensions.Threading;
46

57
public class KeyLocker
68
{
9+
public const long DEFAULT_DEAD_LOCK_TIMES = 100;
10+
11+
private readonly long _deadLockTimes = DEFAULT_DEAD_LOCK_TIMES;
12+
private readonly ILogger? _logger;
713
private static readonly ConcurrentDictionary<string, KeyLockerState<bool>> Lockers = new();
814

15+
public KeyLocker()
16+
{ }
17+
18+
public KeyLocker(long deadLockTimes = DEFAULT_DEAD_LOCK_TIMES, ILogger? logger = null)
19+
{
20+
_deadLockTimes = deadLockTimes;
21+
_logger = logger;
22+
}
23+
924
public async Task WaitAsync(string key, CancellationToken cancellationToken = default)
1025
{
1126
await WaitAsync(key, null, false, cancellationToken);
@@ -18,6 +33,10 @@ public async Task WaitAsync(string key, TimeSpan? timeout = null, CancellationTo
1833

1934
public async Task WaitAsync(string key, TimeSpan? timeout = null, bool releaseAll = false, CancellationToken cancellationToken = default)
2035
{
36+
var stopwatch = new Stopwatch();
37+
38+
stopwatch.Start();
39+
2140
while (!Lockers.TryAdd(key, new KeyLockerState<bool>
2241
{
2342
State = true,
@@ -36,8 +55,13 @@ public async Task WaitAsync(string key, TimeSpan? timeout = null, bool releaseAl
3655
}
3756
}
3857

58+
if (_logger != null && stopwatch.ElapsedMilliseconds >= _deadLockTimes && stopwatch.ElapsedMilliseconds % _deadLockTimes == 0)
59+
_logger.LogWarning("'{Key}' locked for too long, elapsed: {StopwatchElapsed}", key, stopwatch.Elapsed);
60+
3961
await Task.Delay(1, cancellationToken);
4062
}
63+
64+
stopwatch.Stop();
4165
}
4266

4367
public bool Release(string key)
@@ -65,7 +89,7 @@ public void Prune(params string[] keys)
6589
foreach (var key in keysToRemove)
6690
{
6791
if (Lockers.TryGetValue(key, out var locker) && locker.IsExpired)
68-
Lockers.TryRemove(key, out _);
92+
Lockers.TryRemove(key, out _);
6993
}
7094
}
71-
}
95+
}

KeyLockerState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ public class KeyLockerState<T>
55
public T? State { get; set; }
66
public DateTimeOffset? Expires { get; set; }
77
public bool IsExpired => Expires.HasValue && Expires.Value < DateTimeOffset.UtcNow;
8-
}
8+
}

Netcorext.Extensions.Threading.Locker.csproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<LangVersion>latest</LangVersion>
66
<VersionMajor>1</VersionMajor>
77
<VersionMinor>0</VersionMinor>
8-
<VersionPatch>0</VersionPatch>
8+
<VersionPatch>1</VersionPatch>
99
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
1010
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
1111
<FileVersion>$(VersionMajor).$([System.DateTime]::UtcNow.ToString(yy)).$([System.DateTime]::UtcNow.ToString(MMdd)).$([System.DateTime]::UtcNow.ToString(HHmm))</FileVersion>
@@ -22,11 +22,15 @@
2222
<Description>Threading Extensions for .NET Core</Description>
2323
</PropertyGroup>
2424

25+
<ItemGroup>
26+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.*" />
27+
</ItemGroup>
28+
2529
<Target Name="IncludeProjectReferences" DependsOnTargets="ResolveReferences">
2630
<ItemGroup>
2731
<IncludeBuildOutput />
2832
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths-&gt;WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
2933
</ItemGroup>
3034
</Target>
3135

32-
</Project>
36+
</Project>

0 commit comments

Comments
 (0)