public ChangeFeedNotModifiedPage( double requestCharge, string activityId, IReadOnlyDictionary <string, string> additionalHeaders, ChangeFeedState state) : base(requestCharge, activityId, additionalHeaders, state) { }
public static CosmosElement ToCosmosElement(ChangeFeedState changeFeedState) { if (changeFeedState == null) { throw new ArgumentNullException(nameof(changeFeedState)); } return(changeFeedState.Accept(ChangeFeedToCosmosElementVisitor.Singleton)); }
public ChangeFeedSuccessPage( Stream content, double requestCharge, string activityId, ChangeFeedState state) : base(requestCharge, activityId, state) { this.Content = content ?? throw new ArgumentNullException(nameof(content)); }
public ChangeFeedSuccessPage( Stream content, double requestCharge, string activityId, IReadOnlyDictionary <string, string> additionalHeaders, ChangeFeedState state) : base(requestCharge, activityId, additionalHeaders, state) { this.Content = content ?? throw new ArgumentNullException(nameof(content)); }
public async ValueTask <bool> MoveNextAsync() { this.cancellationToken.ThrowIfCancellationRequested(); if (this.bufferedException.HasValue) { this.Current = this.bufferedException.Value; this.bufferedException = null; return(true); } if (!await this.crossPartitionEnumerator.MoveNextAsync()) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } TryCatch <CrossPartitionPage <ChangeFeedPage, ChangeFeedState> > monadicCrossPartitionPage = this.crossPartitionEnumerator.Current; if (monadicCrossPartitionPage.Failed) { this.Current = TryCatch <ChangeFeedPage> .FromException(monadicCrossPartitionPage.Exception); return(true); } CrossPartitionPage <ChangeFeedPage, ChangeFeedState> crossPartitionPage = monadicCrossPartitionPage.Result; ChangeFeedPage backendPage = crossPartitionPage.Page; if (backendPage is ChangeFeedNotModifiedPage) { // Keep draining the cross partition enumerator until // We get a non 304 page or we loop back to the same range or run into an exception FeedRangeInternal originalRange = this.crossPartitionEnumerator.CurrentRange; double totalRequestCharge = backendPage.RequestCharge; do { if (!await this.crossPartitionEnumerator.MoveNextAsync()) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } monadicCrossPartitionPage = this.crossPartitionEnumerator.Current; if (monadicCrossPartitionPage.Failed) { // Buffer the exception, since we need to return the request charge so far. this.bufferedException = TryCatch <ChangeFeedPage> .FromException(monadicCrossPartitionPage.Exception); } else { crossPartitionPage = monadicCrossPartitionPage.Result; backendPage = crossPartitionPage.Page; totalRequestCharge += backendPage.RequestCharge; } }while (!(backendPage is ChangeFeedSuccessPage || this.crossPartitionEnumerator.CurrentRange.Equals(originalRange) || this.bufferedException.HasValue)); // Create a page with the aggregated request charge if (backendPage is ChangeFeedSuccessPage changeFeedSuccessPage) { backendPage = new ChangeFeedSuccessPage( changeFeedSuccessPage.Content, totalRequestCharge, changeFeedSuccessPage.ActivityId, changeFeedSuccessPage.State); } else { backendPage = new ChangeFeedNotModifiedPage( totalRequestCharge, backendPage.ActivityId, backendPage.State); } } CrossPartitionState <ChangeFeedState> crossPartitionState = crossPartitionPage.State; List <CosmosElement> changeFeedContinuationTokens = new List <CosmosElement>(); foreach ((FeedRangeInternal range, ChangeFeedState state)rangeAndState in crossPartitionState.Value) { ChangeFeedContinuationToken changeFeedContinuationToken = new ChangeFeedContinuationToken( rangeAndState.range, rangeAndState.state); CosmosElement cosmosElementChangeFeedContinuationToken = ChangeFeedContinuationToken.ToCosmosElement(changeFeedContinuationToken); changeFeedContinuationTokens.Add(cosmosElementChangeFeedContinuationToken); } CosmosArray cosmosElementTokens = CosmosArray.Create(changeFeedContinuationTokens); ChangeFeedState state = ChangeFeedState.Continuation(cosmosElementTokens); ChangeFeedPage compositePage; if (backendPage is ChangeFeedSuccessPage successPage) { compositePage = new ChangeFeedSuccessPage( successPage.Content, successPage.RequestCharge, successPage.ActivityId, state); } else { compositePage = new ChangeFeedNotModifiedPage( backendPage.RequestCharge, backendPage.ActivityId, state); } this.Current = TryCatch <ChangeFeedPage> .FromResult(compositePage); return(true); }
public static TryCatch <ChangeFeedState> MonadicFromCosmosElement(CosmosElement cosmosElement) { if (cosmosElement == null) { throw new ArgumentNullException(nameof(cosmosElement)); } if (!(cosmosElement is CosmosObject cosmosObject)) { return(TryCatch <ChangeFeedState> .FromException( new FormatException( $"expected change feed state to be an object: {cosmosElement}"))); } if (!cosmosObject.TryGetValue(TypePropertyName, out CosmosString typePropertyValue)) { return(TryCatch <ChangeFeedState> .FromException( new FormatException( $"expected change feed state to have a string type property: {cosmosElement}"))); } ChangeFeedState state; switch (typePropertyValue.Value) { case BeginningTypeValue: state = ChangeFeedState.Beginning(); break; case TimeTypeValue: { if (!cosmosObject.TryGetValue(ValuePropertyName, out CosmosString valuePropertyValue)) { return(TryCatch <ChangeFeedState> .FromException( new FormatException( $"expected change feed state to have a string value property: {cosmosElement}"))); } if (!DateTime.TryParse( valuePropertyValue.Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal | DateTimeStyles.AllowWhiteSpaces, out DateTime utcStartTime)) { return(TryCatch <ChangeFeedState> .FromException( new FormatException( $"failed to parse start time value: {cosmosElement}"))); } state = ChangeFeedState.Time(utcStartTime); } break; case ContinuationTypeValue: { if (!cosmosObject.TryGetValue(ValuePropertyName, out CosmosString valuePropertyValue)) { return(TryCatch <ChangeFeedState> .FromException( new FormatException( $"expected change feed state to have a string value property: {cosmosElement}"))); } state = ChangeFeedState.Continuation(valuePropertyValue); } break; case NowTypeValue: state = ChangeFeedState.Now(); break; default: throw new InvalidOperationException(); } return(TryCatch <ChangeFeedState> .FromResult(state)); }
public ChangeFeedContinuationToken(FeedRangeInternal feedRange, ChangeFeedState changeFeedState) { this.Range = feedRange ?? throw new ArgumentNullException(nameof(feedRange)); this.State = changeFeedState ?? throw new ArgumentNullException(nameof(changeFeedState)); }