private async Task <long> RestartPartition(int partition, int partitionsCount, long start, long end) { var query = new ReadStreamQuery(settings.StreamName) { Coordinates = new StreamCoordinates(new[] { new StreamPosition { Offset = start, Partition = partition } }), ClientShard = partition, ClientShardCount = partitionsCount, Limit = (int)Math.Min(end - start, settings.EventsReadBatchSize) }; var result = await ReadAsync(query).ConfigureAwait(false); try { HandleEvents(result, query.Coordinates); foreach (var window in windows) { window.Value.Flush(true); } } finally { result.Dispose(); } return(result.Next.Positions.Single().Offset); }
public async Task HandleAsync(ReadStreamQuery query, ReadStreamResult streamResult, CancellationToken cancellationToken) { using (iterationMetric?.For("transform_time").Measure()) { var resultingEvents = streamResult.Payload.Events as IEnumerable <HerculesEvent>; if (settings.Filter != null) { resultingEvents = resultingEvents.Where(settings.Filter); } if (settings.Transformer != null) { resultingEvents = resultingEvents.SelectMany(Transform); } buffer.Clear(); buffer.AddRange(resultingEvents); } if (buffer.Count == 0) { return; } using (iterationMetric?.For("write_time").Measure()) { await writer.WriteEvents(buffer, cancellationToken).ConfigureAwait(false); } log.Info("Inserted {EventsCount} event(s) into target stream '{TargetStream}'.", buffer.Count, settings.TargetStreamName); eventsMetric?.For("out").Add(buffer.Count); buffer.Clear(); }
/// <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(); } }
private async Task <RawReadStreamPayload> ReadAsync() { var query = new ReadStreamQuery(settings.StreamName) { Coordinates = coordinates, ClientShard = shardingSettings.ClientShardIndex, ClientShardCount = shardingSettings.ClientShardCount, Limit = settings.EventsReadBatchSize }; return(await ReadAsync(query).ConfigureAwait(false)); }
public async Task <RawReadStreamResult> ReadAsync(ReadStreamQuery query, string apiKey, TimeSpan timeout, CancellationToken cancellationToken = default) { try { var url = new RequestUrlBuilder("stream/read") { { Constants.QueryParameters.Stream, query.Name }, { Constants.QueryParameters.Limit, query.Limit }, { Constants.QueryParameters.ClientShard, query.ClientShard }, { Constants.QueryParameters.ClientShardCount, query.ClientShardCount } } .Build(); var body = CreateRequestBody(query.Coordinates ?? StreamCoordinates.Empty); var request = Request .Post(url) .WithContentTypeHeader(Constants.ContentTypes.OctetStream) .WithContent(body); if (compressionEnabled) { request = request.WithAcceptEncodingHeader(Constants.Compression.Lz4Encoding); } if (!string.IsNullOrEmpty(apiKey)) { request = request.WithHeader(Constants.HeaderNames.ApiKey, apiKey); } var result = await client .SendAsync(request, timeout, cancellationToken : cancellationToken) .ConfigureAwait(false); var operationStatus = responseAnalyzer.Analyze(result.Response, out var errorMessage); if (operationStatus != HerculesStatus.Success) { if (result.Response.HasContent) { bufferPool.Return(result.Response.Content.Buffer); } return(new RawReadStreamResult(operationStatus, null, errorMessage)); } return(new RawReadStreamResult(operationStatus, ParseReadResponseBody(result.Response))); } catch (Exception error) { log.Warn(error); return(new RawReadStreamResult(HerculesStatus.UnknownError, null, error.Message)); } }
public static void WaitForAnyRecord(this IHerculesStreamClient client, string stream) { var readQuery = new ReadStreamQuery(stream) { Limit = 1, Coordinates = new StreamCoordinates(new StreamPosition[0]), ClientShard = 0, ClientShardCount = 1 }; new Action(() => client.Read(readQuery, 20.Seconds()).Payload.Events.Should().NotBeEmpty()) .ShouldPassIn(20.Seconds()); }
public static List <HerculesEvent>[] ReadEvents( this IHerculesStreamClient client, string stream, int count, int limit, int clientShards, StreamCoordinates coordinates = null) { var timeout = 30.Seconds(); var stopwatch = Stopwatch.StartNew(); var eventsRead = 0; var clientShardTasks = Enumerable.Range(0, clientShards).Select(ReadSingleClientShard); var events = Task.WhenAll(clientShardTasks).GetAwaiter().GetResult(); events.Sum(x => x.Count).Should().Be(count); return(events); async Task <List <HerculesEvent> > ReadSingleClientShard(int clientShard) { var shardEvents = new List <HerculesEvent>(); var readQuery = new ReadStreamQuery(stream) { Limit = limit, Coordinates = coordinates ?? StreamCoordinates.Empty, ClientShard = clientShard, ClientShardCount = clientShards }; while (stopwatch.Elapsed < timeout && eventsRead < count) { var result = await client.ReadAsync(readQuery, timeout); result.IsSuccessful.Should().BeTrue(); var eventsFromResponse = result.Payload.Events; shardEvents.AddRange(eventsFromResponse); readQuery.Coordinates = result.Payload.Next; Interlocked.Add(ref eventsRead, eventsFromResponse.Count); await Task.Delay(100); } return(shardEvents); } }
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); } }
public async Task <ReadStreamResult <HerculesEvent> > ReadAsync(ReadStreamQuery query, TimeSpan timeout, CancellationToken cancellationToken = default) { var result = await client.ReadAsync(query, timeout, cancellationToken).ConfigureAwait(false); return(result.ToGenericResult()); }
public static ReadStreamResult Read( [NotNull] this IHerculesStreamClient client, [NotNull] ReadStreamQuery query, TimeSpan timeout, CancellationToken cancellationToken = default) => client.ReadAsync(query, timeout, cancellationToken).GetAwaiter().GetResult();
public Task HandleAsync(ReadStreamQuery query, ReadStreamResult <T> streamResult, CancellationToken cancellationToken) => handler(query, streamResult, cancellationToken);
public async Task <(ReadStreamQuery query, ReadStreamResult <T> result)> ReadAsync( StreamCoordinates coordinates, StreamShardingSettings shardingSettings, long additionalLimit, CancellationToken cancellationToken = default) { log.Info( "Reading logical shard with index {ClientShard} from {ClientShardCount}.", shardingSettings.ClientShardIndex, shardingSettings.ClientShardCount); log.Debug("Current coordinates: {StreamCoordinates}.", coordinates); var eventsQuery = new ReadStreamQuery(settings.StreamName) { Coordinates = coordinates, ClientShard = shardingSettings.ClientShardIndex, ClientShardCount = shardingSettings.ClientShardCount, Limit = (int)Math.Min(settings.EventsReadBatchSize, additionalLimit) }; ReadStreamResult <T> readResult; var remainingAttempts = settings.EventsReadAttempts; do { remainingAttempts--; readResult = await settings.StreamClient.ReadAsync(eventsQuery, settings.EventsReadTimeout, cancellationToken).ConfigureAwait(false); if (!readResult.IsSuccessful && !cancellationToken.IsCancellationRequested) { log.Warn( "Failed to read events from Hercules stream '{StreamName}'. " + "Status: {Status}. Error: '{Error}'. " + "Will try again {RemainingAttempts} more times.", settings.StreamName, readResult.Status, readResult.ErrorDetails, remainingAttempts); if (remainingAttempts > 0) { await Task.Delay(settings.DelayOnError, cancellationToken).SilentlyContinue().ConfigureAwait(false); } } } while (!cancellationToken.IsCancellationRequested && !readResult.IsSuccessful && remainingAttempts > 0); if (readResult.IsSuccessful) { log.Info( "Read {EventsCount} event(s) from Hercules stream '{StreamName}'.", readResult.Payload.Events.Count, settings.StreamName); } else if (cancellationToken.IsCancellationRequested) { log.Info("Cancelled read events request from Hercules stream '{StreamName}'.", settings.StreamName); } else { log.Error( "Failed to read events from Hercules stream '{StreamName}'. " + "Status: {Status}. Error: '{Error}'.", settings.StreamName, readResult.Status, readResult.ErrorDetails); } return(eventsQuery, readResult); }
public async Task <ReadStreamResult> ReadAsync(ReadStreamQuery query, TimeSpan timeout, CancellationToken cancellationToken = new CancellationToken()) { var result = await client.ReadAsync(query, timeout, cancellationToken).ConfigureAwait(false); return(result.FromGenericResult()); }
public Task HandleAsync(ReadStreamQuery query, ReadStreamResult <HerculesEvent> streamResult, CancellationToken cancellationToken) => streamEventsHandler.HandleAsync(query, streamResult.FromGenericResult(), cancellationToken);
public async Task <(ReadStreamQuery query, ReadStreamResult <T> result)> ReadAsync( StreamCoordinates coordinates, StreamShardingSettings shardingSettings, CancellationToken cancellationToken) { log.Info( "Reading logical shard with index {ClientShard} from {ClientShardCount}.", shardingSettings.ClientShardIndex, shardingSettings.ClientShardCount); log.Debug("Current coordinates: {StreamCoordinates}.", coordinates); coordinates = await GetShardCoordinates(coordinates, shardingSettings, cancellationToken).ConfigureAwait(false); log.Debug("Current shard coordinates: {StreamCoordinates}.", coordinates); streamPartitionsCount = streamPartitionsCount ?? await GetPartitionsCount(cancellationToken).ConfigureAwait(false); var current = coordinates.ToDictionary(); foreach (var partition in coordinates.Positions.Select(p => p.Partition)) { var start = current.ContainsKey(partition) ? current[partition].Offset : 0; var end = settings.End.ContainsKey(partition) ? settings.End[partition].Offset : 0; if (start < end) { var count = end - start; log.Info("Reading {EventsCount} events from partition #{Partition}.", count, partition); var(query, result) = await streamReader.ReadAsync( coordinates, // ReSharper disable once PossibleInvalidOperationException new StreamShardingSettings(partition, streamPartitionsCount.Value), count, cancellationToken) .ConfigureAwait(false); result.EnsureSuccess(); result = new ReadStreamResult <T>( result.Status, new ReadStreamPayload <T>( result.Payload.Events, coordinates.SetPosition(result.Payload.Next.Positions.Single())), result.ErrorDetails); query = new ReadStreamQuery(query.Name) { Coordinates = coordinates, ClientShard = shardingSettings.ClientShardIndex, ClientShardCount = shardingSettings.ClientShardCount }; return(query, result); } } return(null, null); }