protected Pool(Configuration.Config config) { NrOfInstances = config.GetInt("nr-of-instances"); Resizer = DefaultResizer.FromConfig(config); UsePoolDispatcher = config.HasPath("pool-dispatcher"); // ReSharper restore DoNotCallOverridableMethodsInConstructor }
protected Pool(Config config) : base(Dispatchers.DefaultDispatcherId) { _nrOfInstances = config.GetInt("nr-of-instances"); _resizer = DefaultResizer.FromConfig(config); _usePoolDispatcher = config.HasPath("pool-dispatcher"); // ReSharper restore DoNotCallOverridableMethodsInConstructor }
/// <summary> /// Creates an instance of the TailChoppingPool. /// </summary> /// <param name="config">The configuration to use with this instance.</param> public TailChoppingPool(Config config) { NrOfInstances = config.GetInt("nr-of-instances"); within = config.GetMillisDuration("within"); interval = config.GetMillisDuration("tail-chopping-router.interval"); Resizer = DefaultResizer.FromConfig(config); UsePoolDispatcher = config.HasPath("pool-dispatcher"); }
public void DefaultResizer_must_use_settings_to_evaluate_rampup() { // ReSharper disable once RedundantArgumentDefaultValue (exposing the values we're testing makes this test understandable.) var resizer = new DefaultResizer(2, 10, rampupRate: 0.2d); resizer.Rampup(9, 10).ShouldBe(0); resizer.Rampup(5, 5).ShouldBe(1); resizer.Rampup(6, 6).ShouldBe(2); }
/// <summary> /// Initializes a new instance of the <see cref="TailChoppingPool"/> class. /// /// <note> /// 'nr-of-instances', 'within', and 'tail-chopping-router.interval' /// must be defined in the provided configuration. /// </note> /// </summary> /// <param name="config">The configuration used to configure the pool.</param> public TailChoppingPool(Config config) : this(config.GetInt("nr-of-instances"), DefaultResizer.FromConfig(config), null, null, //TODO: what are our defaults? null? config.GetTimeSpan("within"), config.GetTimeSpan("tail-chopping-router.interval"), config.HasPath("pool-dispatcher") ) { }
public static Resizer FromConfig(Config parentConfig) { var defaultResizerConfig = parentConfig.GetConfig("resizer"); if (defaultResizerConfig != null && defaultResizerConfig.GetBoolean("enabled")) { return(DefaultResizer.Apply(defaultResizerConfig)); } else { return(null); } }
/// <summary> /// TBD /// </summary> /// <param name="parentConfig">TBD</param> /// <returns>TBD</returns> public static Resizer FromConfig(Config parentConfig) { var defaultResizerConfig = parentConfig.GetConfig("resizer"); if (!defaultResizerConfig.IsNullOrEmpty() && defaultResizerConfig.GetBoolean("enabled", false)) { return(DefaultResizer.Apply(defaultResizerConfig)); } else { return(null); } }
public void DefaultResizer_must_use_settings_to_evaluate_backoff() { // ReSharper disable RedundantArgumentDefaultValue (exposing the values we're testing makes this test understandable.) var resizer = new DefaultResizer(2, 10, backoffThreshold: 0.3d, backoffRate: 0.1d); // ReSharper restore RedundantArgumentDefaultValue resizer.Backoff(10, 10).ShouldBe(0); resizer.Backoff(4, 10).ShouldBe(0); resizer.Backoff(3, 10).ShouldBe(0); resizer.Backoff(2, 10).ShouldBe(-1); resizer.Backoff(0, 10).ShouldBe(-1); resizer.Backoff(1, 9).ShouldBe(-1); resizer.Backoff(0, 9).ShouldBe(-1); }
public void DefaultResizer_must_use_settings_to_evaluate_capacity() { var resizer = new DefaultResizer(2, 3); var c1 = resizer.Capacity(new Routee[] { }); c1.ShouldBe(2); var current = new Routee[] { new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()), new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()) }; var c2 = resizer.Capacity(current); c2.ShouldBe(0); }
public void DefaultResizer_must_use_settings_to_evaluate_capacity() { var resizer = new DefaultResizer(lower: 2, upper: 3); var c1 = resizer.Capacity(Enumerable.Empty<Routee>()); c1.Should().Be(2); var current = new Routee[] { new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()), new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()) }; var c2 = resizer.Capacity(current); c2.Should().Be(0); }
public void DefaultResizer_must_use_settings_to_evaluate_backoff() { var resizer = new DefaultResizer(lower: 2, upper: 10, backoffThreshold: 0.3d, backoffRate: 0.1d); resizer.Backoff(pressure: 10, capacity: 10).Should().Be(0); resizer.Backoff(pressure: 4, capacity: 10).Should().Be(0); resizer.Backoff(pressure: 3, capacity: 10).Should().Be(0); resizer.Backoff(pressure: 2, capacity: 10).Should().Be(-1); resizer.Backoff(pressure: 0, capacity: 10).Should().Be(-1); resizer.Backoff(pressure: 1, capacity: 9).Should().Be(-1); resizer.Backoff(pressure: 0, capacity: 9).Should().Be(-1); }
public void DefaultResizer_must_be_possible_to_define_programmatically() { var latch = new TestLatch(3); var resizer = new DefaultResizer(lower: 2, upper: 3); var router = Sys.ActorOf(new RoundRobinPool(0, resizer).Props(Props.Create<ResizerTestActor>())); router.Tell(latch); router.Tell(latch); router.Tell(latch); latch.Ready(RemainingOrDefault); // MessagesPerResize is 10 so there is no risk of additional resize RouteeSize(router).Should().Be(2); }
public void DefaultResizer_must_be_possible_to_define_programmatically() { var latch = new TestLatch(Sys, 3); var resizer = new DefaultResizer(2, 3); var router = Sys.ActorOf(Props.Create<ResizerTestActor>().WithRouter(new RoundRobinPool(0, resizer))); router.Tell(latch); router.Tell(latch); router.Tell(latch); latch.Ready(TestKitSettings.DefaultTimeout); //messagesPerResize is 10 so there is no risk of additional resize (RouteeSize(router)).ShouldBe(2); }
public void DefaultResizer_must_grow_as_needed_under_pressure() { var resizer = new DefaultResizer( lower: 3, upper: 5, rampupRate: 0.1, backoffRate: 0.0, pressureThreshold: 1, messagesPerResize: 1, backoffThreshold: 0.0); var router = Sys.ActorOf(new RoundRobinPool(0, resizer).Props(Props.Create<PressureActor>())); // first message should create the minimum number of routees router.Tell("echo"); ExpectMsg("reply"); RouteeSize(router).Should().Be(resizer.LowerBound); Action<int, TimeSpan> loop = (loops, d) => { for (var i = 0; i < loops; i++) { router.Tell(d); //sending too quickly will result in skipped resize due to many ResizeInProgress conflicts Thread.Sleep(Dilated(20.Milliseconds())); } double max = d.TotalMilliseconds * loops / resizer.LowerBound + Dilated(2.Seconds()).TotalMilliseconds; Within(TimeSpan.FromMilliseconds(max), () => { for (var i = 0; i < loops; i++) { ExpectMsg("done"); } }); }; // 2 more should go through without triggering more loop(2, 200.Milliseconds()); RouteeSize(router).Should().Be(resizer.LowerBound); // a whole bunch should max it out loop(20, 500.Milliseconds()); RouteeSize(router).Should().Be(resizer.UpperBound); }
public void DefaultResizer_must_grow_as_needed_under_pressure() { var resizer = new DefaultResizer(3, 5, pressureThreshold: 1, rampupRate: 0.1d, backoffRate: 0.0d, messagesPerResize: 1, backoffThreshold: 0.0d); var router = Sys.ActorOf(Props.Create<PressureActor>().WithRouter(new RoundRobinPool(0, resizer))); //first message should create the minimum number of routees router.Tell("echo", TestActor); ExpectMsg("reply", TimeSpan.FromSeconds(1)); (RouteeSize(router)).ShouldBe(resizer.LowerBound); Action<int, TimeSpan> loop = (loops, span) => { for (var i = 0; i < loops; i++) { router.Tell(span, TestActor); //sending too quickly will result in skipped resize due to many resizeInProgress conflicts Thread.Sleep(TimeSpan.FromMilliseconds(20)); } Within( TimeSpan.FromMilliseconds(span.TotalMilliseconds * loops / resizer.LowerBound) + TimeSpan.FromSeconds(2.5), () => { for (var i = 0; i < loops; i++) ExpectMsg("done"); return true; }); }; // 2 more should go through without triggering more loop(2, TimeSpan.FromMilliseconds(200)); RouteeSize(router).ShouldBe(resizer.LowerBound); // a whole bunch should max it out loop(20, TimeSpan.FromMilliseconds(500)); RouteeSize(router).ShouldBe(resizer.UpperBound); }
public void DefaultResizer_must_backoff_within_10_seconds() { var resizer = new DefaultResizer(2, 5, pressureThreshold: 1, rampupRate: 1.0d, backoffRate: 1.0d, messagesPerResize: 2, backoffThreshold: 0.4d); var router = Sys.ActorOf(Props.Create<BackoffActor>().WithRouter(new RoundRobinPool(0, resizer))); // put some pressure on the router for (var i = 0; i < 15; i++) { router.Tell(150); Thread.Sleep(20); } var z = RouteeSize(router); Assert.True(z > 2); Thread.Sleep(300); // let it cool down AwaitCondition(() => { router.Tell(0); //trigger resize Thread.Sleep(20); return RouteeSize(router) < z; }, TimeSpan.FromMilliseconds(500)); }
public void DefaultResizer_must_use_settings_to_evaluate_rampup() { var resizer = new DefaultResizer(lower: 2, upper: 10, rampupRate: 0.2); resizer.Rampup(pressure: 9, capacity: 10).Should().Be(0); resizer.Rampup(pressure: 5, capacity: 5).Should().Be(1); resizer.Rampup(pressure: 6, capacity: 6).Should().Be(2); }
public void DefaultResizer_must_backoff() { Within(TimeSpan.FromSeconds(10), () => { var resizer = new DefaultResizer(2, 5, pressureThreshold: 1, rampupRate: 1.0d, backoffRate: 1.0d, messagesPerResize: 2, backoffThreshold: 0.4d); var router = Sys.ActorOf(Props.Create<BackoffActor>().WithRouter(new RoundRobinPool(0, resizer))); // put some pressure on the router for (var i = 0; i < 200; i++) { router.Tell(150); if (RouteeSize(router) > 2) break; Thread.Sleep(20); } var z = RouteeSize(router); Assert.True(z > 2); Thread.Sleep(300); // let it cool down AwaitAssert(() => { router.Tell(0); //trigger resize Thread.Sleep(20); RouteeSize(router).Should().BeLessThan(z); }, null, TimeSpan.FromSeconds(1)); }); }
public void DefaultResizer_must_grow_as_needed_under_pressure() { var resizer = new DefaultResizer(3, 5, pressureThreshold: 1, rampupRate: 0.1d, backoffRate: 0.0d, messagesPerResize: 1, backoffThreshold: 0.0d); var router = Sys.ActorOf(Props.Create<PressureActor>().WithRouter(new RoundRobinPool(0, resizer))); //first message should create the minimum number of routees router.Tell("echo", TestActor); ExpectMsg("reply"); (RouteeSize(router)).ShouldBe(resizer.LowerBound); Action<int, TimeSpan, int?> loopTillAppropriateSize = (loops, span, expectedBound) => { for (var i = 0; i < loops; i++) { router.Tell(span, TestActor); if (expectedBound.HasValue && RouteeSize(router) >= expectedBound.Value) { return; } //sending too quickly will result in skipped resize due to many resizeInProgress conflicts Thread.Sleep(TimeSpan.FromMilliseconds(20)); } }; // 2 more should go through without triggering more loopTillAppropriateSize(2, TimeSpan.FromMilliseconds(200), null); RouteeSize(router).ShouldBe(resizer.LowerBound); // a whole bunch should max it out loopTillAppropriateSize(200, TimeSpan.FromMilliseconds(500), resizer.UpperBound); RouteeSize(router).ShouldBe(resizer.UpperBound); }
public void DefaultResizer_must_backoff() { Within(10.Seconds(), () => { var resizer = new DefaultResizer( lower: 2, upper: 5, rampupRate: 1.0d, backoffRate: 1.0d, backoffThreshold: 0.40d, pressureThreshold: 1, messagesPerResize: 2); var router = Sys.ActorOf(new RoundRobinPool(nrOfInstances: 0, resizer : resizer) .Props(Props.Create(() => new BackoffActor(Dilated)))); // put some pressure on the router for (var i = 0; i < 15; i++) { router.Tell(150); Thread.Sleep(Dilated(20.Milliseconds())); } var z = RouteeSize(router); z.Should().BeGreaterThan(2); Thread.Sleep(Dilated(300.Milliseconds())); // let it cool down AwaitCondition(() => { router.Tell(0); //trigger resize Thread.Sleep(Dilated(20.Milliseconds())); return RouteeSize(router) < z; }, Dilated(500.Milliseconds())); }); }
protected Pool(Configuration.Config config) { NrOfInstances = config.GetInt("nr-of-instances"); Resizer = DefaultResizer.FromConfig(config); UsePoolDispatcher = config.HasPath("pool-dispatcher"); }