/// <inheritdoc />
        public async Task <ReadStreamResult <T> > ReadAsync(ReadStreamQuery query, TimeSpan timeout, CancellationToken cancellationToken = default)
        {
            var result = await client.ReadAsync(query, settings.ApiKeyProvider(), timeout, cancellationToken).ConfigureAwait(false);

            if (!result.IsSuccessful)
            {
                return(new ReadStreamResult <T>(result.Status, null, result.ErrorDetails));
            }

            var payload = result.Payload;

            try
            {
                var events = EventsBinaryReader.Read(payload.Content, settings.EventBuilderProvider, log);
                return(new ReadStreamResult <T>(result.Status, new ReadStreamPayload <T>(events, payload.Next)));
            }
            catch (Exception error)
            {
                log.Warn(error);
                return(new ReadStreamResult <T>(HerculesStatus.UnknownError, null, error.Message));
            }
            finally
            {
                payload.Dispose();
            }
        }
        protected private async Task <RawReadStreamPayload> ReadAsync(ReadStreamQuery query)
        {
            using (new OperationContextToken("ReadEvents"))
                using (var traceBuilder = tracer.BeginConsumerCustomOperationSpan("Read"))
                    using (iterationMetric?.For("read_time").Measure())
                    {
                        traceBuilder.SetShard(query.ClientShard, query.ClientShardCount);
                        traceBuilder.SetStream(settings.StreamName);
                        traceBuilder.SetCoordinates(query.Coordinates);

                        log.Info(
                            "Reading {EventsCount} events from stream '{StreamName}'. " +
                            "Sharding settings: shard with index {ShardIndex} from {ShardCount}. " +
                            "Coordinates: {StreamCoordinates}.",
                            query.Limit,
                            settings.StreamName,
                            query.ClientShard,
                            query.ClientShardCount,
                            query.Coordinates);
                        traceBuilder.SetOperationDetails(query.Limit);

                        RawReadStreamResult readResult;

                        do
                        {
                            readResult = await client.ReadAsync(query, settings.ApiKeyProvider(), settings.EventsReadTimeout).ConfigureAwait(false);

                            if (!readResult.IsSuccessful)
                            {
                                log.Warn(
                                    "Failed to read events from Hercules stream '{StreamName}'. " +
                                    "Status: {Status}. Error: '{Error}'.",
                                    settings.StreamName,
                                    readResult.Status,
                                    readResult.ErrorDetails);
                                await DelayOnError().ConfigureAwait(false);
                            }
                        } while (!readResult.IsSuccessful);

                        log.Info(
                            "Read {BytesCount} byte(s) from Hercules stream '{StreamName}'.",
                            readResult.Payload.Content.Count,
                            settings.StreamName);

                        return(readResult.Payload);
                    }
        }