Skip to content

Instantly share code, notes, and snippets.

@leppie
Created November 28, 2024 13:10
Show Gist options
  • Save leppie/49551aa98b2ca502b65e29ff449097e0 to your computer and use it in GitHub Desktop.
Save leppie/49551aa98b2ca502b65e29ff449097e0 to your computer and use it in GitHub Desktop.
Sanity checking distributed locking
// spawn multiple instances by spamming `start /b SqlLockTest.exe` (ideally 10+)
using System.Diagnostics;
using Medallion.Threading.SqlServer;
var cs = "Data Source=.;Integrated Security=True;Trust Server Certificate=True;initial catalog=AdventureWorks2022";
var pid = Process.GetCurrentProcess().Id;
var rt = Random.Shared.Next(30, 150);
CancellationTokenSource cts = new(rt * 1000);
var sw = Stopwatch.StartNew();
SqlDistributedLockHandle? lh = null;
WriteLine($"Started");
var lok = new SqlDistributedLock("SomeLock", cs,
opt => opt.KeepaliveCadence(TimeSpan.FromSeconds(30)).UseTransaction(false));
PeriodicTimer timer = new(TimeSpan.FromSeconds(Random.Shared.Next(8, 13)));
try
{
while (await timer.WaitForNextTickAsync(cts.Token))
{
if (lh is null)
{
WriteLine("Try get lock");
lh = await lok.TryAcquireAsync(TimeSpan.FromSeconds(5), cts.Token);
if (lh is null)
{
WriteLine("Lock NOT aquired");
}
else
{
WriteLine("Lock aquired");
}
}
else
{
if (Random.Shared.Next(5) == 0)
{
WriteLine("Random FAILURE!!!!");
Environment.Exit(1);
}
WriteLine("LOCK HOLDER TICK");
}
}
}
catch (OperationCanceledException)
{
//WriteLine("Timer cancelled"); // just noise
}
if (lh is not null)
{
WriteLine("Releasing lock");
await lh.DisposeAsync();
lh = null;
}
WriteLine($"Exiting");
void WriteLine(string s) => Console.WriteLine($"[{(lh is null ? " " : "X")}] [{pid,5}] [{rt - sw.ElapsedMilliseconds/1000,3}] {s}");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment