Skip to content

Instantly share code, notes, and snippets.

@veyodev
Created August 22, 2017 19:52
Show Gist options
  • Save veyodev/8987ce1e98914b00342ac29387fc0f85 to your computer and use it in GitHub Desktop.
Save veyodev/8987ce1e98914b00342ac29387fc0f85 to your computer and use it in GitHub Desktop.
public class DistributedMutex {
private readonly string key;
private readonly string storageConnectionString;
private readonly string storageContainerName;
private CloudBlobClient blobClient;
private string leaseId;
public DistributedMutex(string storageConnectionString, string storageContainerName, string key)
{
this.key = key;
this.storageConnectionString = storageConnectionString;
this.storageContainerName = storageContainerName;
}
/// <summary>
/// Acquires a lease blob.
/// </summary>
public async Task AcquireAsync()
{
var storageAccount = CloudStorageAccount.Parse(storageConnectionString);
blobClient = storageAccount.CreateCloudBlobClient();
var containerReference = blobClient.GetContainerReference(storageContainerName);
await containerReference.CreateIfNotExistsAsync();
var blobReference = containerReference.GetBlockBlobReference(key);
if (!await blobReference.ExistsAsync()) await blobReference.UploadTextAsync(string.Empty);
try {
leaseId = await blobReference.AcquireLeaseAsync(TimeSpan.FromSeconds(60));
}
catch (StorageException ex) {
Console.WriteLine("Error while acquiring an a job lease.");
Console.WriteLine(ex.Message);
if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict) throw new InvalidOperationException($"Another job is already running for {key}.");
throw;
}
}
/// <summary>
/// Releases a lease blob.
/// </summary>
public async Task ReleaseLockAsync()
{
var containerReference = blobClient.GetContainerReference(storageContainerName);
await containerReference.CreateIfNotExistsAsync();
var blobReference = containerReference.GetBlockBlobReference(key);
await blobReference.ReleaseLeaseAsync(new AccessCondition {
LeaseId = leaseId
});
}
/// <summary>
/// Renews the lease.
/// </summary>
public async Task RenewAsync()
{
var containerClientReference = blobClient.GetContainerReference(storageContainerName);
await containerClientReference.CreateIfNotExistsAsync();
var blobReference = containerClientReference.GetBlockBlobReference(key);
await blobReference.RenewLeaseAsync(new AccessCondition {
LeaseId = leaseId
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment