tdd


Prestart being called after failure with stopping strategy


I'm creating retry/reconnect functionality for a actor that is on a remote service. The actor should on prestart call the selection reference to subscribe to messages from the actor on the remote service. If for some reason the actor is not there I want my actor to retry a couple of times before reporting a failure to connect.
I'm using the TestKit to tdd the functionality. The problem I'm running into is that when the actor throws the timeout exception prestart is called afterwards even though I have a stop strategy.
I'm I missunderstanding the lifecycle of the actor? Seems wierd that PreStart is called if the strategy is to stop after failure.
public class MyActor : ReceiveActor
{
private readonly ActorPath path;
private ActorSelection selection;
private int retry = 0;
protected override void PreStart()
{
selection = Context.ActorSelection(path);
selection.Tell("prestart");
SetReceiveTimeout(TimeSpan.FromSeconds(1));
}
public MyActor(ActorPath path)
{
this.path = path;
Receive<ReceiveTimeout>(timeout =>
{
if (retry < 2)
{
retry++;
selection.Tell("retry");
return;
}
throw new Exception("timeout");
});
}
}
public class Test : TestKit
{
[Fact]
public void FactMethodName()
{
var probe = CreateTestProbe();
var props = Props.Create(() => new MyActor(probe.Ref.Path))
.WithSupervisorStrategy(new OneForOneStrategy(exception => Directive.Stop));
Sys.ActorOf(props);
//Initial
probe.ExpectMsg<string>(s => s=="prestart",TimeSpan.FromSeconds(2));
//Retries
probe.ExpectMsg<string>(s => s == "retry", TimeSpan.FromSeconds(2));
probe.ExpectMsg<string>(s => s == "retry", TimeSpan.FromSeconds(2));
//No more
probe.ExpectNoMsg( TimeSpan.FromSeconds(10));
}
}
My Solution after answer from Jeff
public class ParentActor : UntypedActor
{
private readonly Func<IUntypedActorContext, IActorRef> creation;
private IActorRef actorRef;
public ParentActor(Func<IUntypedActorContext, IActorRef> creation)
{
this.creation = creation;
}
protected override void PreStart()
{
actorRef = creation(Context);
}
protected override void OnReceive(object message)
{
actorRef.Tell(message);
}
}
public class MyActor : ReceiveActor
{
private readonly ActorPath path;
private int retry;
private ActorSelection selection;
public MyActor(ActorPath path)
{
this.path = path;
Receive<ReceiveTimeout>(timeout =>
{
if (retry < 2)
{
retry++;
selection.Tell("retry");
return;
}
throw new Exception("timeout");
});
}
protected override void PreStart()
{
selection = Context.ActorSelection(path);
selection.Tell("prestart");
SetReceiveTimeout(TimeSpan.FromSeconds(1));
}
}
public class Test : TestKit
{
[Fact]
public void FactMethodName()
{
var probe = CreateTestProbe();
var props = Props.Create(
() => new ParentActor(context => context.ActorOf(Props.Create(
() => new MyActor(probe.Ref.Path), null), "myactor")))
.WithSupervisorStrategy(new OneForOneStrategy(exception => Directive.Stop));
Sys.ActorOf(props);
//Initial
probe.ExpectMsg<string>(s => s == "prestart", TimeSpan.FromSeconds(2));
//Retries
probe.ExpectMsg<string>(s => s == "retry", TimeSpan.FromSeconds(2));
probe.ExpectMsg<string>(s => s == "retry", TimeSpan.FromSeconds(2));
//No more
probe.ExpectNoMsg(TimeSpan.FromSeconds(10));
}
}
Works but feels like it could be a part of the TestKit to beable set supervisor strategy for the guardian of the test
var props = Props.Create(() => new MyActor(probe.Ref.Path))
.WithSupervisorStrategy(new OneForOneStrategy(exception => Directive.Stop));
This set the supervisor strategy for MyActor, it will be used for MyActor's children and not for MyActor itself.
Sys.ActorOf(props);
This is creating MyActor under the /user guardian which have a OneForOne Restart directive by default. This is why your actor is restarting.
To get what you want, you need to create a parent actor with the custom supervisor strategy and create MyActor under it.

Related Links

TDD and Code Coverage
Testing state in S#arp Architecture - Best practice
TDD System Under Test Creation Patterns (AutoFixture)
What is test-driven development? [duplicate]
Unit tests in TDD
Is Agile different from TDD ? If so what are the main differences?
What are the types of bugs test-driven development is most effective at catching?
TDD with Strategy Pattern
Is there a good place to discuss Test Driven Development?
TDD and UML together
TDD Example for Business Apps
How did/would you “force” yourself to do TDD rather than TAD? [closed]
Test driven development: Inversion of Control (IOC)
What failure modes can TDD leave behind?
Project Implementation estimates with TDD
Too Many Public Methods Forced by Test Driven Development

Categories

HOME
compiler-construction
google-chrome-extension
omnet++
zeromq
nullpointerexception
session
syntax
relay
routes
sqlite-net-extensions
paw-app
leon
sharepoint-designer
youtube-api-v3
jgroups
binary-tree
survey
angular-ui-bootstrap
basic
facebook-messenger-bot
vifm
here-api
commonmark
msp430
serverless-framework
django-simple-history
predix
trading
windows-server-2000
javascriptcore
galsim
create-table
contact-form
google-qpx-express-api
winrt-xaml-toolkit
typed.js
grails-3.1
catalog
host
space-complexity
libvpx
sharefile
no-www
reactive-cocoa-5
wptoolkit
zip4j
dandelion
idisposable
pillow
mcafee
iso8601
spring-mongodb
ableton-live
multiple-regression
connect-by
dataview
kendonumerictextbox
reactive-banana
microbenchmark
splash
mmc
jsapi
fscommand
oxwall
responsive-slides
mysql-error-1062
access-rights
odata4j
hungarian-algorithm
propertyeditor
osql
ohm
custom-backend
subscript
adk
gwt-ext
heartbeat
infobox
tomcat-valve
xdomainrequest
yui-datatable
mysql-error-1005
lpeg
createwindow
asp.net-profiles
multi-tier
procedural-music
msdev
commodore
windows-live-messenger
ajax-forms

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App