private static async Task ManageContainerLeasesAsync(CloudBlobClient blobClient)
{
CloudBlobContainer container1 = null;
CloudBlobContainer container2 = null;
CloudBlobContainer container3 = null;
CloudBlobContainer container4 = null;
CloudBlobContainer container5 = null;
// Lease duration is 15 seconds.
TimeSpan leaseDuration = new TimeSpan(0, 0, 15);
const string LeasingPrefix = "leasing-";
try
{
string leaseId = null;
AccessCondition condition = null;
/*
Case 1: Lease is available
*/
// Lease is available on the new container. Acquire the lease and delete the leased container.
container1 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container1.CreateIfNotExistsAsync();
// Get container properties to see the available lease.
await container1.FetchAttributesAsync();
PrintContainerLeaseProperties(container1);
// Acquire the lease.
leaseId = await container1.AcquireLeaseAsync(leaseDuration, leaseId);
// Get container properties again to see that the container is leased.
await container1.FetchAttributesAsync();
PrintContainerLeaseProperties(container1);
// Create an access condition using the lease ID, and use it to delete the leased container..
condition = new AccessCondition() { LeaseId = leaseId };
await container1.DeleteAsync(condition, null, null);
Console.WriteLine("Deleted container {0}", container1.Name);
/*
Case 2: Lease is breaking
*/
container2 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container2.CreateIfNotExistsAsync();
// Acquire the lease.
leaseId = await container2.AcquireLeaseAsync(leaseDuration, null);
// Break the lease. Passing null indicates that the break interval will be the remainder of the current lease.
await container2.BreakLeaseAsync(null);
// Get container properties to see the breaking lease.
// The lease break interval has not yet elapsed.
await container2.FetchAttributesAsync();
PrintContainerLeaseProperties(container2);
// Delete the container. If the lease is breaking, the container can be deleted by
// passing the lease ID.
condition = new AccessCondition() { LeaseId = leaseId };
await container2.DeleteAsync(condition, null, null);
Console.WriteLine("Deleted container {0}", container2.Name);
/*
Case 3: Lease is broken
*/
container3 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container3.CreateIfNotExistsAsync();
// Acquire the lease.
leaseId = await container3.AcquireLeaseAsync(leaseDuration, null);
// Break the lease. Passing 0 breaks the lease immediately.
TimeSpan breakInterval = await container3.BreakLeaseAsync(new TimeSpan(0));
// Get container properties to see that the lease is broken.
await container3.FetchAttributesAsync();
PrintContainerLeaseProperties(container3);
// Once the lease is broken, delete the container without the lease ID.
await container3.DeleteAsync();
Console.WriteLine("Deleted container {0}", container3.Name);
/*
Case 4: Lease has expired.
*/
container4 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container4.CreateIfNotExistsAsync();
// Acquire the lease.
leaseId = await container4.AcquireLeaseAsync(leaseDuration, null);
// Sleep for 16 seconds to allow lease to expire.
Console.WriteLine("Waiting 16 seconds for lease break interval to expire....");
System.Threading.Thread.Sleep(new TimeSpan(0, 0, 16));
// Get container properties to see that the lease has expired.
await container4.FetchAttributesAsync();
PrintContainerLeaseProperties(container4);
// Delete the container without the lease ID.
await container4.DeleteAsync();
/*
Case 5: Attempt to delete leased container without lease ID.
*/
container5 = blobClient.GetContainerReference(LeasingPrefix + Guid.NewGuid());
await container5.CreateIfNotExistsAsync();
// Acquire the lease.
await container5.AcquireLeaseAsync(leaseDuration, null);
// Get container properties to see that the container has been leased.
await container5.FetchAttributesAsync();
PrintContainerLeaseProperties(container5);
// Attempt to delete the leased container without the lease ID.
// This operation will result in an error.
// Note that in a real-world scenario, it would most likely be another client attempting to delete the container.
await container5.DeleteAsync();
}
catch (StorageException e)
{
if (e.RequestInformation.HttpStatusCode == 412)
{
// Handle the error demonstrated for case 5 above and continue execution.
Console.WriteLine("The container is leased and cannot be deleted without specifying the lease ID.");
Console.WriteLine("More information: {0}", e.Message);
}
else
{
// Output error information for any other errors, but continue execution.
Console.WriteLine(e.Message);
}
}
finally
{
// Enumerate containers based on the prefix used to name them, and delete any remaining containers.
foreach (var container in blobClient.ListContainers(LeasingPrefix))
{
await container.FetchAttributesAsync();
if (container.Properties.LeaseState == LeaseState.Leased || container.Properties.LeaseState == LeaseState.Breaking)
{
await container.BreakLeaseAsync(new TimeSpan(0));
}
Console.WriteLine();
Console.WriteLine("Deleting container: {0}", container.Name);
await container.DeleteAsync();
}
}
}