/// <inheritdoc/> public Lease FromLeaseToken(string leaseToken) { if (leaseToken is null) { throw new ArgumentNullException(nameof(leaseToken)); } return(AzureLease.FromToken(this, leaseToken)); }
/// <inheritdoc/> public async Task <Lease> AcquireAsync(LeasePolicy leasePolicy, string?proposedLeaseId = null) { if (leasePolicy is null) { throw new ArgumentNullException(nameof(leasePolicy)); } this.logger.LogDebug($"Acquiring lease for '{leasePolicy.ActorName}' with name '{leasePolicy.Name}', duration '{leasePolicy.Duration}', and proposed id '{proposedLeaseId}'"); try { await this.InitialiseAsync().ConfigureAwait(false); // Once Initialise has been called, we know this.container is set. CloudBlockBlob blob = this.container !.GetBlockBlobReference((leasePolicy.Name ?? Guid.NewGuid().ToString()).ToLowerInvariant()); await Retriable.RetryAsync( async() => { try { if (!await blob.ExistsAsync().ConfigureAwait(false)) { using var ms = new MemoryStream(); await blob.UploadFromStreamAsync(ms).ConfigureAwait(false); } } catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == 400) { // Turn that into an invalid operation exception for standard "bad request" semantics (bad name) throw new InvalidOperationException(); } catch (ArgumentOutOfRangeException) { // Turn that into an invalid operation exception for standard "bad request" semantics (bad duration) throw new InvalidOperationException(); } }, CancellationToken.None, new Count(10), new AggregatePolicy { Policies = { new DoNotRetryOnInvalidOperationPolicy(), new DoNotRetryOnConflictPolicy(), new DoNotRetryOnInitializationFailurePolicy() } }).ConfigureAwait(false); string id = await Retriable.RetryAsync( async() => { try { return(await blob.AcquireLeaseAsync(leasePolicy.Duration, proposedLeaseId)); } catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == 400) { // Turn that into an invalid operation exception for standard "bad request" semantics (bad name) throw new InvalidOperationException(); } catch (ArgumentOutOfRangeException) { // Turn that into an invalid operation exception for standard "bad request" semantics (bad duration) throw new InvalidOperationException(); } }, CancellationToken.None, new Count(10), new AggregatePolicy { Policies = { new DoNotRetryOnInvalidOperationPolicy(), new DoNotRetryOnConflictPolicy(), new DoNotRetryOnInitializationFailurePolicy() } }).ConfigureAwait(false); var lease = new AzureLease(this, leasePolicy, id); lease.SetLastAcquired(DateTimeOffset.Now); this.logger.LogDebug($"Acquired lease for '{leasePolicy.ActorName}' with name '{leasePolicy.Name}', duration '{leasePolicy.Duration}', and actual id '{id}'"); return(lease); } catch (StorageException exception) { if (exception.RequestInformation.HttpStatusCode == 409) { this.logger.LogError($"Failed to acquire lease for '{leasePolicy.ActorName}'. The lease was held by another party. The lease name was '{leasePolicy.Name}', duration '{leasePolicy.Duration}', and proposed id '{proposedLeaseId}'"); throw new LeaseAcquisitionUnsuccessfulException(leasePolicy, exception); } else { this.logger.LogError($"Failed to acquire lease for '{leasePolicy.ActorName}' due to storage failure. The lease name was '{leasePolicy.Name}', duration '{leasePolicy.Duration}', and proposed id '{proposedLeaseId}'"); throw; } } catch (InitializationFailureException) { this.logger.LogError($"Failed to acquire lease for '{leasePolicy.ActorName}' due to storage intiialization failure. The lease name was '{leasePolicy.Name}', duration '{leasePolicy.Duration}', and proposed id '{proposedLeaseId}'"); throw; } }