From 80f4c6e77b38c60ba7365e0e8065fa032175ad4c Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 13 Sep 2024 18:44:28 -0500 Subject: [PATCH] Avoid constantly attempting to acquire a lock - ignore expiration timeout on WaitForChangesAsync when there are queued writer locks --- .../Services/DistributedReaderWriterLock.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Machine/src/Serval.Machine.Shared/Services/DistributedReaderWriterLock.cs b/src/Machine/src/Serval.Machine.Shared/Services/DistributedReaderWriterLock.cs index 51c11f82..e5963575 100644 --- a/src/Machine/src/Serval.Machine.Shared/Services/DistributedReaderWriterLock.cs +++ b/src/Machine/src/Serval.Machine.Shared/Services/DistributedReaderWriterLock.cs @@ -73,8 +73,8 @@ public async Task ReaderLockAsync( RWLock? rwLock = sub.Change.Entity; if (rwLock is not null && !rwLock.IsAvailableForReading()) { - TimeSpan? timeout = default; - if (rwLock.WriterLock?.ExpiresAt is not null) + TimeSpan? timeout = null; + if (rwLock.WriterQueue.Count == 0 && rwLock.WriterLock?.ExpiresAt is not null) { timeout = rwLock.WriterLock.ExpiresAt - DateTime.UtcNow; if (timeout < TimeSpan.Zero) @@ -138,15 +138,18 @@ await _locks.UpdateAsync( RWLock? rwLock = sub.Change.Entity; if (rwLock is not null && !rwLock.IsAvailableForWriting(lockId)) { - var dateTimes = rwLock.ReaderLocks.Select(l => l.ExpiresAt).ToList(); - if (rwLock.WriterLock?.ExpiresAt is not null) - dateTimes.Add(rwLock.WriterLock.ExpiresAt); - TimeSpan? timeout = default; - if (dateTimes.Count > 0) + TimeSpan? timeout = null; + if (rwLock.WriterQueue[0].Id == lockId) { - timeout = dateTimes.Max() - DateTime.UtcNow; - if (timeout < TimeSpan.Zero) - timeout = TimeSpan.Zero; + var dateTimes = rwLock.ReaderLocks.Select(l => l.ExpiresAt).ToList(); + if (rwLock.WriterLock?.ExpiresAt is not null) + dateTimes.Add(rwLock.WriterLock.ExpiresAt); + if (dateTimes.Count > 0) + { + timeout = dateTimes.Max() - DateTime.UtcNow; + if (timeout < TimeSpan.Zero) + timeout = TimeSpan.Zero; + } } if (timeout != TimeSpan.Zero) await sub.WaitForChangeAsync(timeout, cancellationToken);