Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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;
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        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));
        }
Esempio n. 6
0
 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);
        }
Esempio n. 8
0
        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));
        }
Esempio n. 10
0
        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;
            }
        }