public void A_StatefulSelectMany_must_be_able_to_restart() { var probe = Source.From(new[] { 2, 1, 3, 4, 1 }).StatefulSelectMany <int, int, NotUsed>(() => { int?prev = null; return(x => { if (x % 3 == 0) { throw Ex; } if (prev.HasValue) { var result = Enumerable.Range(1, prev.Value).Select(__ => x); prev = x; return result; } prev = x; return new List <int>(); }); }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)) .RunWith(this.SinkProbe <int>(), Materializer); probe.Request(2).ExpectNext(1, 1); probe.Request(4).ExpectNext(1, 1, 1, 1); probe.ExpectComplete(); }
public async Task A_QueueSink_should_skip_failing_messages_if_supervision_strategy_is_restart() { await Queue.DeleteIfExistsAsync(); var queueSink = QueueSink.Create(Queue) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)); var t = this.SourceProbe <string>() //.Select(x => new QueueMessage(x)) .ToMaterialized(queueSink, Keep.Both) .Run(Materializer); var probe = t.Item1; var task = t.Item2; probe.SendNext("1"); await Task.Delay(500); await Queue.CreateAsync(); probe.SendNext("2"); probe.SendComplete(); await task; (await Queue.ReceiveMessagesAsync()).Value[0].MessageText.Should().Be("2"); }
public void Conflate_must_restart_when_aggregate_throws_and_a_RestartingDecider_is_used() { var sourceProbe = this.CreatePublisherProbe <string>(); var sinkProbe = this.CreateSubscriberProbe <string>(); var latch = new TestLatch(); var conflate = Flow.Create <string>().ConflateWithSeed(i => i, (state, elem) => { if (elem == "two") { latch.Open(); throw new TestException("two is a three letter word"); } return(state + elem); }).WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)); Source.FromPublisher(sourceProbe) .Via(conflate) .To(Sink.FromSubscriber(sinkProbe)) .WithAttributes(Attributes.CreateInputBuffer(4, 4)) .Run(Materializer); var sub = sourceProbe.ExpectSubscription(); sub.ExpectRequest(4); sub.SendNext("one"); sub.SendNext("two"); sub.SendNext("three"); sub.SendComplete(); //"one" should be lost latch.Ready(TimeSpan.FromSeconds(3)); sinkProbe.RequestNext("three"); }
public async Task PlainSource_should_stop_on_errors() { int elementsCount = 10; var topic1 = CreateTopic(1); var group1 = CreateGroup(1); await ProduceStrings(new TopicPartition(topic1, 0), Enumerable.Range(1, elementsCount), ProducerSettings); var settings = CreateConsumerSettings <int>(group1).WithValueDeserializer(Deserializers.Int32); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.StoppingDecider)) .Select(c => c.Value) .RunWith(this.SinkProbe <int>(), Materializer); var error = probe.Request(elementsCount).ExpectEvent(TimeSpan.FromSeconds(5)); error.Should().BeOfType <TestSubscriber.OnError>(); var exception = ((TestSubscriber.OnError)error).Cause; exception.Should().BeOfType <ConsumeException>(); ((ConsumeException)exception).Error.IsSerializationError().Should().BeTrue(); probe.ExpectNoMsg(TimeSpan.FromSeconds(5)); probe.Cancel(); }
public void A_Flow_with_SelectAsync_must_resume_after_task_failure() { this.AssertAllStagesStopped(() => { this.AssertAllStagesStopped(() => { var c = this.CreateManualSubscriberProbe <int>(); Source.From(Enumerable.Range(1, 5)) .SelectAsync(4, n => Task.Run(() => { if (n == 3) { throw new TestException("err3"); } return(n); })) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(Sink.FromSubscriber(c), Materializer); var sub = c.ExpectSubscription(); sub.Request(10); new[] { 1, 2, 4, 5 }.ForEach(i => c.ExpectNext(i)); c.ExpectComplete(); }, Materializer); }, Materializer); }
public void A_LazySink_must_continue_if_supervision_is_resume() { this.AssertAllStagesStopped(() => { var sourceProbe = this.CreateManualPublisherProbe <int>(); var lazySink = Sink.LazySink((int a) => { if (a == 0) { throw Ex; } return(Task.FromResult(this.SinkProbe <int>())); }, Fallback <TestSubscriber.Probe <int> >()); var taskProbe = Source.FromPublisher(sourceProbe) .ToMaterialized(lazySink, Keep.Right) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .Run(Materializer); var sourceSub = sourceProbe.ExpectSubscription(); sourceSub.ExpectRequest(1); sourceSub.SendNext(0); sourceSub.ExpectRequest(1); sourceSub.SendNext(1); var probe = taskProbe.AwaitResult(RemainingOrDefault); probe.Request(1); probe.ExpectNext(1); probe.Cancel(); }, Materializer); }
public async Task Overriden_default_decider_on_PlainSource_should_work() { int elementsCount = 10; var topic1 = CreateTopic(1); var group1 = CreateGroup(1); var sourceTask = ProduceStrings(new TopicPartition(topic1, 0), Enumerable.Range(1, elementsCount), ProducerSettings); await GuardWithTimeoutAsync(sourceTask, TimeSpan.FromSeconds(3)); var settings = CreateConsumerSettings <int>(group1).WithValueDeserializer(Deserializers.Int32); var decider = new OverridenConsumerDecider(settings.AutoCreateTopicsEnabled); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(decider.Decide)) .Select(c => c.Value) .RunWith(this.SinkProbe <int>(), Materializer); probe.Request(elementsCount); probe.ExpectNoMsg(TimeSpan.FromSeconds(10)); // this is twice elementCount because Decider is called twice on each exceptions decider.CallCount.Should().Be(elementsCount * 2); probe.Cancel(); }
public void A_UnfoldResourceSource_must_close_and_open_stream_again_when_strategy_is_restart() { this.AssertAllStagesStopped(() => { var p = Source.UnfoldResource(_open, reader => { var s = reader.ReadLine(); if (s != null && s.Contains("b")) { throw new TestException(""); } return(s ?? Option <string> .None); }, Close) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)) .RunWith(Sink.AsPublisher <string>(false), Materializer); var c = this.CreateManualSubscriberProbe <string>(); p.Subscribe(c); var sub = c.ExpectSubscription(); Enumerable.Range(0, 20).ForEach(i => { sub.Request(1); c.ExpectNext().Should().Be(ManyLinesArray[0]); }); sub.Cancel(); }, Materializer); }
public void A_ForeachParallel_must_finish_after_function_thrown_exception() { this.AssertAllStagesStopped(() => { var probe = CreateTestProbe(); var latch = new TestLatch(1); var p = Source.From(Enumerable.Range(1, 5)).RunWith(Sink.ForEachParallel <int>(3, n => { if (n == 3) { throw new TestException("err2"); } probe.Ref.Tell(n); latch.Ready(TimeSpan.FromSeconds(10)); }).WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.StoppingDecider)), Materializer); // make sure the stream is up and running, otherwise the latch is maybe ready before the third message arrives Thread.Sleep(500); latch.CountDown(); probe.ExpectMsgAllOf(1, 2); var ex = p.Invoking(t => t.Wait(TimeSpan.FromSeconds(1))).Should().Throw <AggregateException>().Which; ex.Flatten().InnerException.Should().BeOfType <TestException>(); ex.Flatten().InnerException.Message.Should().Be("err2"); p.IsCompleted.Should().BeTrue(); }, Materializer); }
public async Task PlainSource_with_directive_override_should_resume_on_deserialization_errors() { var callCount = 0; Directive Decider(Exception cause) { if (cause is ConsumeException ex && ex.Error.IsSerializationError()) { callCount++; return(Directive.Resume); } return(Directive.Stop); } int elementsCount = 10; var topic1 = CreateTopic(1); var group1 = CreateGroup(1); await ProduceStrings(new TopicPartition(topic1, 0), Enumerable.Range(1, elementsCount), ProducerSettings); var settings = CreateConsumerSettings <int>(group1).WithValueDeserializer(Deserializers.Int32); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Decider)) .Select(c => c.Value) .RunWith(this.SinkProbe <int>(), Materializer); probe.Request(elementsCount); probe.ExpectNoMsg(TimeSpan.FromSeconds(10)); // this is twice elementCount because Decider is called twice on each exceptions callCount.Should().Be(elementsCount * 2); probe.Cancel(); }
/// <summary> /// KafkaSourceStage /// </summary> /// <param name="stageName">Stage name</param> /// <param name="autoCreateTopics">Kafka source should auto create topics</param> protected KafkaSourceStage(string stageName) { StageName = stageName; Shape = new SourceShape <TMessage>(Out); InitialAttributes = Attributes.CreateName(StageName) .And(ActorAttributes.CreateSupervisionStrategy(new DefaultConsumerDecider(true).Decide)); }
public void A_AggregateAsync_must_restart_after_task_failure() { this.AssertAllStagesStopped(() => { var probe = this.CreateSubscriberProbe <Tuple <int, int> >(); Source.From(Enumerable.Range(1, 5)).AggregateAsync(Tuple.Create(0, 1), (t, n) => { var i = t.Item1; var res = t.Item2; return(Task.Run(() => { if (n == 3) { throw new Exception("err3"); } return Tuple.Create(n, i + res * n); })); }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)) .To(Sink.FromSubscriber(probe)) .Run(Materializer); var subscription = probe.ExpectSubscription(); subscription.Request(10); probe.ExpectNext(Tuple.Create(5, 24)); probe.ExpectComplete(); }, Materializer); }
public async Task PlainPartitionedSource_should_be_signalled_about_serialization_errors() { var topic = CreateTopic(1); var group = CreateGroup(1); await ProduceStrings(topic, new int[] { 0 }, ProducerSettings); // Produce "0" string var settings = CreateConsumerSettings <int>(group).WithValueDeserializer(Deserializers.Int32); var(control1, partitionedProbe) = KafkaConsumer.PlainPartitionedSource(settings, Subscriptions.Topics(topic)) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.StoppingDecider)) .ToMaterialized(this.SinkProbe <(TopicPartition, Source <ConsumeResult <Null, int>, NotUsed>)>(), Keep.Both) .Run(Materializer); partitionedProbe.Request(3); var subsources = partitionedProbe.Within(TimeSpan.FromSeconds(10), () => partitionedProbe.ExpectNextN(3).Select(t => t.Item2).ToList()); var substream = subsources.Aggregate((s1, s2) => s1.Merge(s2)).RunWith(this.SinkProbe <ConsumeResult <Null, int> >(), Materializer); substream.Request(1); await ProduceStrings(topic, new int[] { 0 }, ProducerSettings); // Produce "0" string Within(TimeSpan.FromSeconds(10), () => substream.ExpectError().Should().BeOfType <SerializationException>()); var shutdown = control1.Shutdown(); AwaitCondition(() => shutdown.IsCompleted, TimeSpan.FromSeconds(10)); }
public void Flow_with_ask_a_failure_mid_stream_must_skip_element_with_resume_strategy() => this.AssertAllStagesStopped(() => { var p = CreateTestProbe(); var input = new[] { "a", "b", "c", "d", "e", "f" }; var elements = Source.From(input) .Ask <string>(p.Ref, _timeout, 5) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Supervision.Deciders.ResumingDecider)) .RunWith(Sink.Seq <string>(), _materializer); // the problematic ordering: p.ExpectMsg("a"); p.LastSender.Tell("a"); p.ExpectMsg("b"); p.LastSender.Tell("b"); p.ExpectMsg("c"); var cSender = p.LastSender; p.ExpectMsg("d"); p.LastSender.Tell("d"); p.ExpectMsg("e"); p.LastSender.Tell("e"); p.ExpectMsg("f"); p.LastSender.Tell("f"); cSender.Tell(new Status.Failure(new Exception("Boom!"))); elements.Result.Should().BeEquivalentTo(new[] { "a", "b", /*no c*/ "d", "e", "f" }); }, _materializer);
public void A_UnfoldResourceAsyncSource_must_continue_when_strategy_is_resume_and_exception_happened() { this.AssertAllStagesStopped(() => { var p = Source.UnfoldResourceAsync(_open, reader => { var s = reader.ReadLine(); if (s != null && s.Contains("b")) { throw new TestException(""); } return(Task.FromResult(s ?? Option <string> .None)); }, Close) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(Sink.AsPublisher <string>(false), Materializer); var c = this.CreateManualSubscriberProbe <string>(); p.Subscribe(c); var sub = c.ExpectSubscription(); Enumerable.Range(0, 50).ForEach(i => { sub.Request(1); c.ExpectNext().Should().Be(i < 10 ? ManyLinesArray[i] : ManyLinesArray[i + 10]); }); sub.Request(1); c.ExpectComplete(); }, Materializer); }
public async Task PlainSource_should_resume_on_deserialization_errors() { Directive Decider(Exception cause) => cause is SerializationException ? Directive.Resume : Directive.Stop; int elementsCount = 10; var topic1 = CreateTopic(1); var group1 = CreateGroup(1); await Produce(topic1, Enumerable.Range(1, elementsCount), ProducerSettings); var settings = ConsumerSettings <Null, int> .Create(Sys, null, new IntDeserializer()) .WithBootstrapServers(KafkaUrl) .WithProperty("auto.offset.reset", "earliest") .WithGroupId(group1); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Decider)) .Select(c => c.Value) .RunWith(this.SinkProbe <int>(), _materializer); probe.Request(elementsCount); probe.ExpectNoMsg(TimeSpan.FromSeconds(10)); probe.Cancel(); }
public void Stream_supervision_must_support_restart() { var withAttributes = FailingMap.WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)); var result = Run(withAttributes); result.ShouldAllBeEquivalentTo(new[] { 1, 2, 4, 5, 1, 2, 4, 5 }); }
public async Task PlainSink_should_resume_on_deserialization_errors() { var callCount = 0; Directive Decider(Exception cause) { callCount++; switch (cause) { case ProduceException <Null, string> ex when ex.Error.IsSerializationError(): return(Directive.Resume); default: return(Directive.Stop); } } var elementsCount = 10; var topic1 = CreateTopic(1); var group1 = CreateGroup(1); var producerSettings = ProducerSettings <Null, string> .Create(Sys, null, new FailingSerializer()) .WithBootstrapServers(Fixture.KafkaServer); var sink = KafkaProducer.PlainSink(producerSettings) .AddAttributes(ActorAttributes.CreateSupervisionStrategy(Decider)); var sourceTask = Source .From(new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }) .Select(elem => new ProducerRecord <Null, string>(new TopicPartition(topic1, 0), elem.ToString())) .RunWith(sink, Materializer); var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5)); var completeTask = await Task.WhenAny(sourceTask, timeoutTask); if (completeTask == timeoutTask) { throw new Exception("Producer timed out"); } var settings = CreateConsumerSettings <Null, string>(group1).WithValueDeserializer(new StringDeserializer()); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .Select(c => c.Value) .RunWith(this.SinkProbe <string>(), Materializer); probe.Request(elementsCount); for (var i = 0; i < 9; i++) { Log.Info($">>>>>>>>>>> {i}"); probe.ExpectNext(); } callCount.Should().Be(1); probe.Cancel(); }
public void Conflate_must_restart_when_aggregate_throws_and_a_ResumingDecider_is_used() { var sourceProbe = this.CreatePublisherProbe <int>(); var sinkProbe = this.CreateManualSubscriberProbe <List <int> >(); var saw4Latch = new TestLatch(); var graph = Source.FromPublisher(sourceProbe).ConflateWithSeed(i => new List <int> { i }, (state, elem) => { if (elem == 2) { throw new TestException("three is a four letter word"); } if (elem == 4) { saw4Latch.Open(); } state.Add(elem); return(state); }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .To(Sink.FromSubscriber(sinkProbe)) .WithAttributes(Attributes.CreateInputBuffer(1, 1)); RunnableGraph.FromGraph(graph).Run(Materializer); var sub = sourceProbe.ExpectSubscription(); var sinkSub = sinkProbe.ExpectSubscription(); // push the first three values, the third will trigger // the exception sub.ExpectRequest(1); sub.SendNext(1); // causing the 1 to get thrown away sub.ExpectRequest(1); sub.SendNext(2); sub.ExpectRequest(1); sub.SendNext(3); sub.ExpectRequest(1); sub.SendNext(4); // and consume it, so that the next element // will trigger seed saw4Latch.Ready(TimeSpan.FromSeconds(3)); sinkSub.Request(1); sinkProbe.ExpectNext().ShouldAllBeEquivalentTo(new [] { 1, 3, 4 }); }
public void Flow_with_ask_must_resume_after_multiple_failures() => this.AssertAllStagesStopped(() => { var aref = ReplierFailAllExceptOn(6); var t = Source.From(Enumerable.Range(1, 6)) .Ask <Reply>(aref, _timeout, 2) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Supervision.Deciders.ResumingDecider)) .RunWith(Sink.First <Reply>(), _materializer); t.Wait(3.Seconds()).Should().BeTrue(); t.Result.Should().Be(new Reply(6)); }, _materializer);
public void A_Log_on_Source_must_follow_supervision_strategy_when_Exception_thrown() { var ex = new TestException("test"); var future = Source.From(Enumerable.Range(1, 5)) .Log("hi", n => { throw ex; }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(Sink.Aggregate <int, int>(0, (i, i1) => i + i1), Materializer); future.Wait(TimeSpan.FromMilliseconds(500)).Should().BeTrue(); future.Result.Should().Be(0); }
private TestSubscriber.ManualProbe <string> WhenNullElement(ICollection <string> elements, string zero, Decider decider = null) { decider = decider ?? Deciders.StoppingDecider; return(Source.From(elements) .ScanAsync(zero, (i, i1) => Task.FromResult(i1 != "null" ? i1 : null)) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(decider)) .RunWith(this.SinkProbe <string>(), Materializer) .Request(elements.Count + 1) .ExpectNext(zero)); }
public void GroupBy_must_resume_stream_when_GroupBy_function_throws() { this.AssertAllStagesStopped(() => { var publisherProbe = TestPublisher.CreateManualProbe <int>(this); var ex = new TestException("test"); var publisher = Source.FromPublisher(publisherProbe).GroupBy(2, i => { if (i == 2) { throw ex; } return(i % 2); }) .Lift(x => x % 2) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(Sink.AsPublisher <Tuple <int, Source <int, NotUsed> > >(false), Materializer); var subscriber = TestSubscriber.CreateManualProbe <Tuple <int, Source <int, NotUsed> > >(this); publisher.Subscribe(subscriber); var upstreamSubscription = publisherProbe.ExpectSubscription(); var downstreamSubscription = subscriber.ExpectSubscription(); downstreamSubscription.Request(100); upstreamSubscription.SendNext(1); var substream = subscriber.ExpectNext().Item2; var substreamPuppet1 = new StreamPuppet(substream.RunWith(Sink.AsPublisher <int>(false), Materializer), this); substreamPuppet1.Request(10); substreamPuppet1.ExpectNext(1); upstreamSubscription.SendNext(2); upstreamSubscription.SendNext(4); var substream2 = subscriber.ExpectNext().Item2; var substreamPuppet2 = new StreamPuppet(substream2.RunWith(Sink.AsPublisher <int>(false), Materializer), this); substreamPuppet2.Request(10); substreamPuppet2.ExpectNext(4); upstreamSubscription.SendNext(3); substreamPuppet1.ExpectNext(3); upstreamSubscription.SendNext(6); substreamPuppet2.ExpectNext(6); upstreamSubscription.SendComplete(); subscriber.ExpectComplete(); substreamPuppet1.ExpectComplete(); substreamPuppet2.ExpectComplete(); }, Materializer); }
public async Task SupervisionStrategy_Decider_on_PlainSink_should_work() { var callCount = 0; Directive Decider(Exception cause) { callCount++; switch (cause) { case ProduceException <Null, string> ex when ex.Error.IsSerializationError(): return(Directive.Resume); default: return(Directive.Stop); } } var topic1 = CreateTopic(1); var group1 = CreateGroup(1); var producerSettings = ProducerSettings <Null, string> .Create(Sys, null, new FailingSerializer()) .WithBootstrapServers(Fixture.KafkaServer); // Exception is injected into the sink by the FailingSerializer serializer, it throws an exceptions // when the message "5" is encountered. var sourceTask = Source .From(new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }) .Select(elem => new ProducerRecord <Null, string>(new TopicPartition(topic1, 0), elem.ToString())) .RunWith( KafkaProducer.PlainSink(producerSettings) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Decider)), Materializer); await GuardWithTimeoutAsync(sourceTask, TimeSpan.FromSeconds(5)); var settings = CreateConsumerSettings <Null, string>(group1).WithValueDeserializer(new StringDeserializer()); var probe = KafkaConsumer .PlainSource(settings, Subscriptions.Assignment(new TopicPartition(topic1, 0))) .Select(c => c.Value) .RunWith(this.SinkProbe <string>(), Materializer); probe.Request(10); for (var i = 0; i < 9; i++) { var message = probe.ExpectNext(); Log.Info($"> [{i}]: {message}"); } callCount.Should().Be(1); probe.Cancel(); }
public void A_Flow_with_SelectAsyncUnordered_must_resume_when_task_is_completed_with_null() { var c = TestSubscriber.CreateManualProbe <string>(this); Source.From(new[] { "a", "b", "c" }) .SelectAsyncUnordered(4, s => s.Equals("b") ? Task.FromResult(null as string) : Task.FromResult(s)) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .To(Sink.FromSubscriber(c)).Run(Materializer); var sub = c.ExpectSubscription(); sub.Request(10); c.ExpectNextUnordered("a", "c"); c.ExpectComplete(); }
public async Task SupervisionStrategy_Decider_on_Consumer_Downstream_should_work() { var topic = CreateTopic(1); var group = CreateGroup(1); var topicPartition = new TopicPartition(topic, 0); var callCount = 0; Directive Decider(Exception cause) { callCount++; if (cause.Message == "BOOM!") { return(Directive.Restart); } return(Directive.Stop); } var consumerSettings = CreateConsumerSettings <string>(group); var counter = 0; await Source.From(Enumerable.Range(1, 11)) .Select(elem => new ProducerRecord <Null, string>(topicPartition, elem.ToString())) .RunWith(KafkaProducer.PlainSink(ProducerSettings), Materializer); var(_, probe) = KafkaConsumer .PlainSource(consumerSettings, Subscriptions.Assignment(topicPartition)) .Select(c => { counter++; // fail once on counter 5 if (counter == 5) { throw new Exception("BOOM!"); } return(c.Message.Value); }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Decider)) .ToMaterialized(this.SinkProbe <string>(), Keep.Both) .Run(Materializer); probe.Request(10); for (var i = 0; i < 9; i++) { var message = probe.ExpectNext(TimeSpan.FromSeconds(10)); Log.Info(message); } probe.Cancel(); callCount.Should().Be(1); }
public void A_QueueSink_should_retry_failing_messages_if_supervision_strategy_is_resume() { Queue.DeleteIfExists(); var messages = new[] { "1", "2" }; var queueSink = QueueSink.Create(Queue) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)); var t = Source.From(messages) .Select(x => new CloudQueueMessage(x)) .RunWith(queueSink, Materializer); Thread.Sleep(1000); Queue.Create(); t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); Queue.GetMessages(2).Select(x => x.AsString).ShouldAllBeEquivalentTo(messages); }
public void Conflate_must_restart_when_seed_throws_and_a_RestartDescider_is_used() { var sourceProbe = this.CreatePublisherProbe <int>(); var sinkProbe = this.CreateManualSubscriberProbe <int>(); var exceptionlath = new TestLatch(); var graph = Source.FromPublisher(sourceProbe).ConflateWithSeed(i => { if (i % 2 == 0) { exceptionlath.Open(); throw new TestException("I hate even seed numbers"); } return(i); }, (sum, i) => sum + i) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)) .To(Sink.FromSubscriber(sinkProbe)) .WithAttributes(Attributes.CreateInputBuffer(1, 1)); RunnableGraph.FromGraph(graph).Run(Materializer); var sub = sourceProbe.ExpectSubscription(); var sinkSub = sinkProbe.ExpectSubscription(); // push the first value sub.ExpectRequest(1); sub.SendNext(1); // and consume it, so that the next element // will trigger seed sinkSub.Request(1); sinkProbe.ExpectNext(1); sub.ExpectRequest(1); sub.SendNext(2); // make sure the seed exception happened // before going any further exceptionlath.Ready(TimeSpan.FromSeconds(3)); sub.ExpectRequest(1); sub.SendNext(3); // now we should have lost the 2 and the accumulated state sinkSub.Request(1); sinkProbe.ExpectNext(3); }
public void A_Flow_with_SelectAsyncUnordered_must_resume_when_SelectAsyncUnordered_throws() { Source.From(Enumerable.Range(1, 5)) .SelectAsyncUnordered(4, n => { if (n == 3) { throw new TestException("err4"); } return(Task.FromResult(n)); }) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.ResumingDecider)) .RunWith(this.SinkProbe <int>(), Materializer) .Request(10) .ExpectNextUnordered(1, 2, 4, 5) .ExpectComplete(); }
public void A_Collect_must_restart_when_Collect_throws() { bool ThrowOnTwo(int x) => x == 2 ? throw new TestException("") : true; var probe = Source.From(Enumerable.Range(1, 3)) .Collect(ThrowOnTwo, x => x) .WithAttributes(ActorAttributes.CreateSupervisionStrategy(Deciders.RestartingDecider)) .RunWith(this.SinkProbe <int>(), Materializer); probe.Request(1); probe.ExpectNext(1); probe.Request(1); probe.ExpectNext(3); probe.Request(1); probe.ExpectComplete(); }