public async Task <bool> TryLockOrRenew(CancellationToken cancellationToken) { await EnsureContainerExists(cancellationToken).ConfigureAwait(false); if (lease == null) { try { lease = await container.AcquireLeaseAsync(span, null, null, null, null, cancellationToken).ConfigureAwait(false); return(true); } catch (StorageException exception) when(exception.RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict) { return(false); } } try { await container.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(lease), null, null, cancellationToken).ConfigureAwait(false); return(true); } catch (StorageException exception) when(exception.RequestInformation.ErrorCode == BlobErrorCodeStrings.LeaseIdMismatchWithLeaseOperation) { lease = null; return(false); } }
async Task <bool> TryAquireLeaseAsync() { bool leaseAcquired; try { this.settings.Logger.LeaseAcquisitionStarted( this.accountName, this.taskHub, this.workerName, this.appLeaseContainerName); await appLeaseContainer.AcquireLeaseAsync(this.options.LeaseInterval, this.appLeaseId); await this.UpdateOwnerAppIdToCurrentApp(); leaseAcquired = true; this.settings.Logger.LeaseAcquisitionSucceeded( this.accountName, this.taskHub, this.workerName, this.appLeaseContainerName); } catch (StorageException e) { leaseAcquired = false; this.settings.Logger.LeaseAcquisitionFailed( this.accountName, this.taskHub, this.workerName, this.appLeaseContainerName); this.settings.Logger.PartitionManagerWarning( this.accountName, this.taskHub, this.workerName, this.appLeaseContainerName, $"Failed to acquire app lease with appLeaseId {this.appLeaseId}. Another app likely has the lease on this container. Exception: {e.Message}"); } finally { this.stats.StorageRequests.Increment(); } return(leaseAcquired); }
public async Task AcquireLockAsync(string key, int numRetries, TimeSpan waitBetweenRetries, TimeSpan lockTimeout, CancellationToken cancellationToken) { _logger.LogInformation($"Acquiring lock for key {key} ..."); var storage = CreateStorageAccountFromConnectionString(_settings.AzureStorageConnectionString); var storageClient = storage.CreateCloudBlobClient(); _storageContainer = storageClient.GetContainerReference(key); await _storageContainer.CreateIfNotExistsAsync(); await _storageContainer.FetchAttributesAsync(); await Policy.Handle <StorageException>().WaitAndRetryAsync(numRetries, n => { _logger.LogInformation($"Failed to acquire lock. Retrying ... (retry count {n})"); return(waitBetweenRetries); }).ExecuteAsync(async() => { _leaseId = await _storageContainer.AcquireLeaseAsync(lockTimeout); }); }
private async Task <HttpResponseMessage> SetContainerLease(CloudBlobContainer container) { IEnumerable <string> action; string leaseId = null; string proposedLeaseId = null; HttpResponseMessage response = new HttpResponseMessage(); AccessCondition condition; string serverLeaseId; await AddBasicContainerHeaders(response, container); //If an action is not provided, it's not a valid call. if (!Request.Headers.TryGetValues("x-ms-lease-action", out action)) { response.StatusCode = HttpStatusCode.BadRequest; return(response); } if (Request.Headers.Contains("x-ms-lease-id")) { leaseId = Request.Headers.GetValues("x-ms-lease-id").FirstOrDefault(); } if (Request.Headers.Contains("x-ms-proposed-lease-id")) { proposedLeaseId = Request.Headers.GetValues("x-ms-proposed-lease-id").FirstOrDefault(); } switch (action.First().ToLower()) { case "acquire": int leaseDuration = Int32.Parse(Request.Headers.GetValues("x-ms-lease-duration").First()); TimeSpan?leaseDurationSpan; if (leaseDuration == -1) { leaseDurationSpan = null; } else if (leaseDuration >= 15 && leaseDuration <= 60) { leaseDurationSpan = new TimeSpan(0, 0, leaseDuration); } else { response.StatusCode = HttpStatusCode.BadRequest; return(response); } serverLeaseId = await container.AcquireLeaseAsync(leaseDurationSpan, proposedLeaseId); response = new DelegatedResponse(await ContainerHandler.DoForDataContainersAsync(container.Name, HttpStatusCode.Created, async containerObj => await containerObj.AcquireLeaseAsync(leaseDurationSpan, serverLeaseId), true)).CreateResponse(); await AddBasicContainerHeaders(response, container); response.Headers.Add("x-ms-lease-id", serverLeaseId); return(response); case "renew": condition = new AccessCondition() { LeaseId = leaseId }; response = new DelegatedResponse(await ContainerHandler.DoForAllContainersAsync(container.Name, HttpStatusCode.OK, async containerObj => await containerObj.RenewLeaseAsync(condition), true)).CreateResponse(); await AddBasicContainerHeaders(response, container); response.Headers.Add("x-ms-lease-id", leaseId); return(response); case "change": condition = new AccessCondition() { LeaseId = leaseId }; serverLeaseId = await container.ChangeLeaseAsync(proposedLeaseId, condition); response = new DelegatedResponse(await ContainerHandler.DoForDataContainersAsync(container.Name, HttpStatusCode.OK, async containerObj => await containerObj.ChangeLeaseAsync(proposedLeaseId, condition), true)).CreateResponse(); await AddBasicContainerHeaders(response, container); response.Headers.Add("x-ms-lease-id", container.ChangeLease(proposedLeaseId, condition)); return(response); case "release": condition = new AccessCondition() { LeaseId = leaseId }; response = new DelegatedResponse(await ContainerHandler.DoForAllContainersAsync(container.Name, HttpStatusCode.OK, async containerObj => await containerObj.ReleaseLeaseAsync(condition), true)).CreateResponse(); await AddBasicContainerHeaders(response, container); return(response); case "break": int breakDuration = 0; if (Request.Headers.Contains("x-ms-lease-break-period")) { breakDuration = Int32.Parse(Request.Headers.GetValues("x-ms-lease-break-period").FirstOrDefault()); } TimeSpan breakDurationSpan = new TimeSpan(0, 0, breakDuration); TimeSpan remainingTime = await container.BreakLeaseAsync(breakDurationSpan); response = new DelegatedResponse(await ContainerHandler.DoForDataContainersAsync(container.Name, HttpStatusCode.Accepted, async containerObj => await containerObj.BreakLeaseAsync(breakDurationSpan), true)).CreateResponse(); await AddBasicContainerHeaders(response, container); response.Headers.Add("x-ms-lease-time", remainingTime.Seconds.ToString()); return(response); default: //Not a recognized action response.StatusCode = HttpStatusCode.BadRequest; return(response); } }