/// <summary> /// Returns <see cref="BlobChangeFeedEvent"/>s as Pages. /// </summary> /// <param name="continuationToken"> /// Throws an <see cref="ArgumentException"/>. To use contination, call /// <see cref="BlobChangeFeedClient.GetChanges(string)"/>. /// </param> /// <param name="pageSizeHint"> /// Page size. /// </param> /// <returns> /// <see cref="IEnumerable{Page}"/>. /// </returns> public override IEnumerable <Page <BlobChangeFeedEvent> > AsPages(string continuationToken = null, int?pageSizeHint = null) { if (continuationToken != null) { throw new ArgumentException($"Continuation not supported. Use BlobChangeFeedClient.GetChanges(string) instead"); } ChangeFeed changeFeed = _changeFeedFactory.BuildChangeFeed( async: false, _startTime, _endTime, _continuation) .EnsureCompleted(); while (changeFeed.HasNext()) { yield return(changeFeed.GetPage( async: false, pageSize: pageSizeHint ?? 512).EnsureCompleted()); } }
/// <summary> /// Returns <see cref="BlobChangeFeedEvent"/>s as Pages. /// </summary> /// <param name="continuationToken"> /// Throws an <see cref="ArgumentException"/>. To use contination, call /// <see cref="BlobChangeFeedClient.GetChangesAsync(string)"/>. /// </param> /// <param name="pageSizeHint"> /// Page size. /// </param> /// <returns> /// <see cref="IAsyncEnumerable{Page}"/>. /// </returns> public override async IAsyncEnumerable <Page <BlobChangeFeedEvent> > AsPages( string continuationToken = null, int?pageSizeHint = null) { if (continuationToken != null) { throw new ArgumentException($"{nameof(continuationToken)} not supported. Use BlobChangeFeedClient.GetChangesAsync(string) instead"); } ChangeFeed changeFeed = await _changeFeedFactory.BuildChangeFeed( _startTime, _endTime, _continuation, async : true, cancellationToken : default) .ConfigureAwait(false); while (changeFeed.HasNext()) { yield return(await changeFeed.GetPage( async : true, pageSize : pageSizeHint ?? Constants.ChangeFeed.DefaultPageSize).ConfigureAwait(false)); } }
public async Task <ChangeFeed> BuildChangeFeed( bool async, DateTimeOffset?startTime = default, DateTimeOffset?endTime = default, string continuation = default) { DateTimeOffset lastConsumable; Queue <string> years = new Queue <string>(); Queue <string> segments = new Queue <string>(); ChangeFeedCursor cursor = null; // Create cursor if (continuation != null) { cursor = JsonSerializer.Deserialize <ChangeFeedCursor>(continuation); ValidateCursor(_containerClient, cursor); startTime = cursor.CurrentSegmentCursor.SegmentTime; endTime = cursor.EndTime; } // Round start and end time if we are not using the cursor. else { startTime = startTime.RoundDownToNearestHour(); endTime = endTime.RoundUpToNearestHour(); } // Check if Change Feed has been abled for this account. bool changeFeedContainerExists; if (async) { changeFeedContainerExists = await _containerClient.ExistsAsync().ConfigureAwait(false); } else { changeFeedContainerExists = _containerClient.Exists(); } if (!changeFeedContainerExists) { throw new ArgumentException("Change Feed hasn't been enabled on this account, or is currently being enabled."); } // Get last consumable BlobClient blobClient = _containerClient.GetBlobClient(Constants.ChangeFeed.MetaSegmentsPath); BlobDownloadInfo blobDownloadInfo; if (async) { blobDownloadInfo = await blobClient.DownloadAsync().ConfigureAwait(false); } else { blobDownloadInfo = blobClient.Download(); } JsonDocument jsonMetaSegment; if (async) { jsonMetaSegment = await JsonDocument.ParseAsync(blobDownloadInfo.Content).ConfigureAwait(false); } else { jsonMetaSegment = JsonDocument.Parse(blobDownloadInfo.Content); } lastConsumable = jsonMetaSegment.RootElement.GetProperty("lastConsumable").GetDateTimeOffset(); // Get year paths years = await GetYearPaths(async).ConfigureAwait(false); // Dequeue any years that occur before start time if (startTime.HasValue) { while (years.Count > 0 && years.Peek().ToDateTimeOffset() < startTime.RoundDownToNearestYear()) { years.Dequeue(); } } // There are no years. if (years.Count == 0) { return(ChangeFeed.Empty()); } while (segments.Count == 0 && years.Count > 0) { // Get Segments for year segments = await BlobChangeFeedExtensions.GetSegmentsInYear( async : async, containerClient : _containerClient, yearPath : years.Dequeue(), startTime : startTime, endTime : BlobChangeFeedExtensions.MinDateTime(lastConsumable, endTime)) .ConfigureAwait(false); } // We were on the last year, and there were no more segments. if (segments.Count == 0) { return(ChangeFeed.Empty()); } Segment currentSegment = await _segmentFactory.BuildSegment( async, segments.Dequeue(), cursor?.CurrentSegmentCursor) .ConfigureAwait(false); return(new ChangeFeed( _containerClient, _segmentFactory, years, segments, currentSegment, lastConsumable, startTime, endTime)); }