private static string GetFirstItemLSN(Collection <JObject> items)
        {
            JObject item = RemainingWorkEstimatorCore.GetFirstItem(items);

            if (item == null)
            {
                return(null);
            }

            if (item.TryGetValue(LSNPropertyName, StringComparison.OrdinalIgnoreCase, out JToken property))
            {
                return(property.Value <string>());
            }

            DefaultTrace.TraceWarning("Change Feed response item does not include LSN.");
            return(null);
        }
        private async Task <long> GetRemainingWorkAsync(DocumentServiceLease existingLease, CancellationToken cancellationToken)
        {
            // Current lease schema maps Token to PKRangeId
            string partitionKeyRangeId = existingLease.CurrentLeaseToken;

            using FeedIterator iterator = this.feedCreator(
                      partitionKeyRangeId,
                      existingLease.ContinuationToken,
                      string.IsNullOrEmpty(existingLease.ContinuationToken));

            try
            {
                ResponseMessage response = await iterator.ReadNextAsync(cancellationToken).ConfigureAwait(false);

                if (response.StatusCode != HttpStatusCode.NotModified)
                {
                    response.EnsureSuccessStatusCode();
                }

                long parsedLSNFromSessionToken = RemainingWorkEstimatorCore.TryConvertToNumber(ExtractLsnFromSessionToken(response.Headers[HttpConstants.HttpHeaders.SessionToken]));
                IEnumerable <JObject> items    = RemainingWorkEstimatorCore.GetItemsFromResponse(response);
                long lastQueryLSN = items.Any()
                    ? RemainingWorkEstimatorCore.TryConvertToNumber(RemainingWorkEstimatorCore.GetFirstItemLSN(items)) - 1
                    : parsedLSNFromSessionToken;
                if (lastQueryLSN < 0)
                {
                    return(1);
                }

                long leaseTokenRemainingWork = parsedLSNFromSessionToken - lastQueryLSN;
                return(leaseTokenRemainingWork < 0 ? 0 : leaseTokenRemainingWork);
            }
            catch (Exception clientException)
            {
                Cosmos.Extensions.TraceException(clientException);
                DefaultTrace.TraceWarning("GetEstimateWork > exception: lease token '{0}'", existingLease.CurrentLeaseToken);
                throw;
            }
        }