Skip to content

Conversation

@Holymaan
Copy link
Contributor

@Holymaan Holymaan commented Sep 3, 2025

Added new method TryGetAcquireLocks and override for ReleaseAppLock method to work with lists.

Zlatko Zajec and others added 2 commits September 3, 2025 11:49
✨feat: Added new method TryGetAcquireLocks and override for ReleaseAppLock method to work with lists.
return allReleased;
}

public static async Task<bool> TryGetAcquireLocks(this SqlConnection connection, IEnumerable<int> keys, int retryTimeout = 100, int numberOfRetries = 3, IDbTransaction transaction = null, TimeSpan? lockTimeout = null)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep the name aligned with existing GetAppLockAsync, this should be TryGetAppLockAsync


public static async Task<bool> TryGetAcquireLocks(this SqlConnection connection, IEnumerable<int> keys, int retryTimeout = 100, int numberOfRetries = 3, IDbTransaction transaction = null, TimeSpan? lockTimeout = null)
{
if (keys == null)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should also be a check if there is 0 keys in the IEnumerable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check added.


foreach (var key in keys)
{
var lockName = $"Sql_lock_{key}";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't modify the name, the caller should pass in unique names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

{
var lockName = $"Sql_lock_{key}";
var locked = await connection.GetAppLockAsync(lockName, transaction, lockTimeout);
if (locked)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd write this differently so it's more clear what the expected flow is.

if (!locked)
{
    allLocked = false;
    break;
}

acquiredLocks.Add(lockName);

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can achieve the intent of the code without using a list of acquiredLocks. Looking at a scenario where in vast majority of cases locks will go through on the first go creating and discarding a list of names of acquired locks is a bit of waste.

You only need to track the index of the last created lock and then to ReleaseAppLockAsync you can pass something like this

connection.ReleaseAppLockAsync(keys.Take(index+1), transaction);

This way you take only one int in most scenarios, and in those scenarios where you do need to release them you then spend some extra computing, but that should be rare.

}
}

if (!allLocked)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also rewrite this

if (allLocked)
    break;

await connection.ReleaseAppLockAsync(....);
await Task.Delay(retryTimeout);

}
}

return false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There here

return allLocked;

@lukaferlez lukaferlez merged commit dc2809d into lukaferlez:master Sep 3, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants