Esempio n. 1
0
        public virtual async Task <List <BlobChangeFeedEvent> > GetPage(
            bool async,
            int?pageSize,
            CancellationToken cancellationToken = default)
        {
            List <BlobChangeFeedEvent> changeFeedEventList = new List <BlobChangeFeedEvent>();

            if (!HasNext())
            {
                throw new InvalidOperationException("Segment doesn't have any more events");
            }

            int i = 0;

            while (i < pageSize && _shards.Count > 0)
            {
                // If this Shard is finished, skip it.
                if (_finishedShards.Contains(_shardIndex))
                {
                    _shardIndex++;

                    if (_shardIndex == _shards.Count)
                    {
                        _shardIndex = 0;
                    }

                    continue;
                }

                Shard currentShard = _shards[_shardIndex];

                BlobChangeFeedEvent changeFeedEvent = await currentShard.Next(async, cancellationToken).ConfigureAwait(false);

                changeFeedEventList.Add(changeFeedEvent);

                // If the current shard is completed, remove it from _shards
                if (!currentShard.HasNext())
                {
                    _finishedShards.Add(_shardIndex);
                }

                i++;
                _shardIndex++;
                if (_shardIndex >= _shards.Count)
                {
                    _shardIndex = 0;
                }

                // If all the Shards are finished, we need to break out early.
                if (_finishedShards.Count == _shards.Count)
                {
                    break;
                }
            }

            return(changeFeedEventList);
        }
#pragma warning disable CA1822 // Does not acces instance data can be marked static.
        public virtual async Task <Segment> BuildSegment(
#pragma warning restore CA1822 // Can't mock static methods in MOQ.
            bool async,
            string manifestPath,
            SegmentCursor cursor = default)
        {
            // Models we need for later
            List <Shard>   shards   = new List <Shard>();
            DateTimeOffset dateTime = BlobChangeFeedExtensions.ToDateTimeOffset(manifestPath).Value;

            // Download segment manifest
            BlobClient       blobClient = _containerClient.GetBlobClient(manifestPath);
            BlobDownloadInfo blobDownloadInfo;

            if (async)
            {
                blobDownloadInfo = await blobClient.DownloadAsync().ConfigureAwait(false);
            }
            else
            {
                blobDownloadInfo = blobClient.Download();
            }

            // Parse segment manifest
            JsonDocument jsonManifest;

            if (async)
            {
                jsonManifest = await JsonDocument.ParseAsync(blobDownloadInfo.Content).ConfigureAwait(false);
            }
            else
            {
                jsonManifest = JsonDocument.Parse(blobDownloadInfo.Content);
            }

            foreach (JsonElement shardJsonElement in jsonManifest.RootElement.GetProperty("chunkFilePaths").EnumerateArray())
            {
                string shardPath   = shardJsonElement.ToString().Substring("$blobchangefeed/".Length);
                var    shardCursor = cursor?.ShardCursors?.Find(x => x.CurrentChunkPath.StartsWith(shardPath, StringComparison.InvariantCulture));
                Shard  shard       = await _shardFactory.BuildShard(
                    async,
                    shardPath,
                    shardCursor)
                                     .ConfigureAwait(false);

                if (shard.HasNext())
                {
                    shards.Add(shard);
                }
            }

            int    shardIndex       = 0;
            string currentShardPath = cursor?.CurrentShardPath;

            if (!string.IsNullOrWhiteSpace(currentShardPath))
            {
                shardIndex = shards.FindIndex(s => s.ShardPath == currentShardPath);
                if (shardIndex < 0)
                {
                    // Either shard doesn't exist or cursor is pointing to end of shard. So start from beginning.
                    shardIndex = 0;
                }
            }
            return(new Segment(
                       shards,
                       shardIndex,
                       dateTime,
                       manifestPath));
        }