public override async Task <DocumentServiceLease> CreateLeaseIfNotExistAsync(string leaseToken, string continuationToken) { if (leaseToken == null) { throw new ArgumentNullException(nameof(leaseToken)); } string leaseDocId = this.GetDocumentId(leaseToken); var documentServiceLease = new DocumentServiceLeaseCore { LeaseId = leaseDocId, LeaseToken = leaseToken, ContinuationToken = continuationToken, }; bool created = await this.leaseContainer.TryCreateItemAsync <DocumentServiceLeaseCore>( this.requestOptionsFactory.GetPartitionKey(documentServiceLease.Id), documentServiceLease).ConfigureAwait(false) != null; if (created) { DefaultTrace.TraceInformation("Created lease with lease token {0}.", leaseToken); return(documentServiceLease); } DefaultTrace.TraceInformation("Some other host created lease for {0}.", leaseToken); return(null); }
private async Task <DocumentServiceLeaseCore> TryReplaceLeaseAsync(DocumentServiceLeaseCore lease, object partitionKey, string itemId) { try { CosmosItemResponse <DocumentServiceLeaseCore> response = await this.container.Items.ReplaceItemAsync <DocumentServiceLeaseCore>( partitionKey, itemId, lease, this.CreateIfMatchOptions(lease)).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.NotFound) { throw new LeaseLostException(lease, true); } return(response.Resource); } catch (CosmosException ex) { Logger.WarnFormat("Lease operation exception, status code: ", ex.StatusCode); if (ex.StatusCode == HttpStatusCode.PreconditionFailed) { return(null); } if (ex.StatusCode == HttpStatusCode.Conflict) { throw new LeaseLostException(lease, ex, false); } throw; } }
public override async Task ReleaseAsync(DocumentServiceLease lease) { if (lease == null) { throw new ArgumentNullException(nameof(lease)); } DocumentServiceLeaseCore refreshedLease = await this.TryGetLeaseAsync(lease).ConfigureAwait(false); if (refreshedLease == null) { DefaultTrace.TraceInformation("Lease with token {0} failed to release lease. The lease is gone already.", lease.CurrentLeaseToken); throw new LeaseLostException(lease); } await this.leaseUpdater.UpdateLeaseAsync( refreshedLease, refreshedLease.Id, this.requestOptionsFactory.GetPartitionKey(lease.Id), serverLease => { if (serverLease.Owner != lease.Owner) { DefaultTrace.TraceInformation("Lease with token {0} no need to release lease. The lease was already taken by another host '{1}'.", lease.CurrentLeaseToken, serverLease.Owner); throw new LeaseLostException(lease); } serverLease.Owner = null; return(serverLease); }).ConfigureAwait(false); }
public override async Task <DocumentServiceLease> RenewAsync(DocumentServiceLease lease) { if (lease == null) { throw new ArgumentNullException(nameof(lease)); } // Get fresh lease. The assumption here is that checkpointing is done with higher frequency than lease renewal so almost // certainly the lease was updated in between. DocumentServiceLeaseCore refreshedLease = await this.TryGetLeaseAsync(lease).ConfigureAwait(false); if (refreshedLease == null) { DefaultTrace.TraceInformation("Lease with token {0} failed to renew lease. The lease is gone already.", lease.CurrentLeaseToken); throw new LeaseLostException(lease); } return(await this.leaseUpdater.UpdateLeaseAsync( refreshedLease, refreshedLease.Id, this.requestOptionsFactory.GetPartitionKey(lease.Id), serverLease => { if (serverLease.Owner != lease.Owner) { DefaultTrace.TraceInformation("Lease with token {0} was taken over by owner '{1}'", lease.CurrentLeaseToken, serverLease.Owner); throw new LeaseLostException(lease); } return serverLease; }).ConfigureAwait(false)); }
public override Task <DocumentServiceLease> CreateLeaseIfNotExistAsync(string leaseToken, string continuationToken) { if (leaseToken == null) { throw new ArgumentNullException(nameof(leaseToken)); } DocumentServiceLeaseCore documentServiceLease = new DocumentServiceLeaseCore { LeaseId = leaseToken, LeaseToken = leaseToken, ContinuationToken = continuationToken, }; bool created = this.container.TryAdd( leaseToken, documentServiceLease); if (created) { DefaultTrace.TraceInformation("Created lease with lease token {0}.", leaseToken); return(Task.FromResult <DocumentServiceLease>(documentServiceLease)); } DefaultTrace.TraceInformation("Some other host created lease for {0}.", leaseToken); return(Task.FromResult <DocumentServiceLease>(null)); }
public DocumentServiceLeaseCore(DocumentServiceLeaseCore other) { this.LeaseId = other.LeaseId; this.LeaseToken = other.LeaseToken; this.Owner = other.Owner; this.ContinuationToken = other.ContinuationToken; this.ETag = other.ETag; this.TS = other.TS; this.ExplicitTimestamp = other.ExplicitTimestamp; this.Properties = other.Properties; }
public override async Task <DocumentServiceLease> UpdateLeaseAsync( DocumentServiceLease cachedLease, string itemId, Cosmos.PartitionKey partitionKey, Func <DocumentServiceLease, DocumentServiceLease> updateLease) { DocumentServiceLease lease = cachedLease; for (int retryCount = RetryCountOnConflict; retryCount >= 0; retryCount--) { lease = updateLease(lease); if (lease == null) { return(null); } lease.Timestamp = DateTime.UtcNow; DocumentServiceLeaseCore leaseDocument = await this.TryReplaceLeaseAsync((DocumentServiceLeaseCore)lease, partitionKey, itemId).ConfigureAwait(false); if (leaseDocument != null) { return(leaseDocument); } DefaultTrace.TraceInformation("Lease with token {0} update conflict. Reading the current version of lease.", lease.CurrentLeaseToken); try { ItemResponse <DocumentServiceLeaseCore> response = await this.container.ReadItemAsync <DocumentServiceLeaseCore>( itemId, partitionKey).ConfigureAwait(false); DocumentServiceLeaseCore serverLease = response.Resource; DefaultTrace.TraceInformation( "Lease with token {0} update failed because the lease with concurrency token '{1}' was updated by host '{2}' with concurrency token '{3}'. Will retry, {4} retry(s) left.", lease.CurrentLeaseToken, lease.ConcurrencyToken, serverLease.Owner, serverLease.ConcurrencyToken, retryCount); lease = serverLease; } catch (CosmosException ex) when(ex.StatusCode == HttpStatusCode.NotFound) { DefaultTrace.TraceInformation("Lease with token {0} no longer exists", lease.CurrentLeaseToken); throw new LeaseLostException(lease, true); } } throw new LeaseLostException(lease); }
public override Task <DocumentServiceLease> CreateLeaseIfNotExistAsync( PartitionKeyRange partitionKeyRange, string continuationToken) { if (partitionKeyRange == null) { throw new ArgumentNullException(nameof(partitionKeyRange)); } string leaseToken = partitionKeyRange.Id; DocumentServiceLeaseCore documentServiceLease = new DocumentServiceLeaseCore { LeaseId = leaseToken, LeaseToken = leaseToken, ContinuationToken = continuationToken, FeedRange = new FeedRangeEpk(partitionKeyRange.ToRange()) }; return(this.TryCreateDocumentServiceLeaseAsync(documentServiceLease)); }
public override Task <DocumentServiceLease> CreateLeaseIfNotExistAsync( PartitionKeyRange partitionKeyRange, string continuationToken) { if (partitionKeyRange == null) { throw new ArgumentNullException(nameof(partitionKeyRange)); } string leaseToken = partitionKeyRange.Id; string leaseDocId = this.GetDocumentId(leaseToken); DocumentServiceLeaseCore documentServiceLease = new DocumentServiceLeaseCore { LeaseId = leaseDocId, LeaseToken = leaseToken, ContinuationToken = continuationToken, FeedRange = new FeedRangeEpk(partitionKeyRange.ToRange()) }; this.requestOptionsFactory.AddPartitionKeyIfNeeded((string pk) => documentServiceLease.LeasePartitionKey = pk, Guid.NewGuid().ToString()); return(this.TryCreateDocumentServiceLeaseAsync(documentServiceLease)); }
private async Task <DocumentServiceLeaseCore> TryReplaceLeaseAsync( DocumentServiceLeaseCore lease, Cosmos.PartitionKey partitionKey, string itemId) { try { ItemRequestOptions itemRequestOptions = this.CreateIfMatchOptions(lease); ItemResponse <DocumentServiceLeaseCore> response = await this.container.ReplaceItemAsync <DocumentServiceLeaseCore>( id : itemId, item : lease, partitionKey : partitionKey, requestOptions : itemRequestOptions).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.NotFound) { throw new LeaseLostException(lease, true); } return(response.Resource); } catch (CosmosException ex) { DefaultTrace.TraceWarning("Lease operation exception, status code: {0}", ex.StatusCode); if (ex.StatusCode == HttpStatusCode.PreconditionFailed) { return(null); } if (ex.StatusCode == HttpStatusCode.Conflict) { throw new LeaseLostException(lease, ex, false); } throw; } }