This has brought to light some interesting effects (aka bugs) both in
the general implementation as well as in previous fixes.
SupervisorHierarchySpec is without TODOs now and GREEN.
fix two bugs:
- resumeChildren should only check the perpetrator if
inResponseToFailure is true
- handleInvokeFailure must not suspend the survivors in case of an
exception in postRestart
- always suspend/resume for Suspend/Resume/Recreate, no matter which
state the actor is in, to keep the counter balanced
- preRestart failures are logged but otherwise ignored; there’s nothing
else (apart from terminating the actor) which we could do at that
point
- preRestart/postRestart exceptions have their own distinguishable
subtype of ActorKilledException now
- fix some race conditions in tests to make them produce fewer false
failures
- remove cruft from SupervisorStrategy and add methods which can
actually be used to implement your own (with proper warning signs)
- introducing RepointableActorRef, which starts out with an
UnstartedActorCell which can cheaply be created; the Supervise()
message will trigger child.activate() in the supervisor, which means
that the actual creation (now with normal ActorCell) happens exactly
in the right place and with the right semantics. Messages which were
enqueued to the dummy cell are transferred atomically into the
ActorCell (using normal .tell()), so message sends keep working
exactly as they used to
- this enables getting rid of the brittle synchronization around
RoutedActorRef by replacing that one with a RepointableActorRef
subclass which creates RoutedActorCells upon activate(), with the nice
benefit that there is no hurry then to get it right because the new
cell is constructed “on the side”
misc fixes:
- InvalidMessageException is now actually enforced when trying to send
“null”
- Mailboxes may be created without having an ActorCell, which can come
in handy later, because the cell is only needed when this mailbox is
going to be scheduled on some executor
- remove occurrences of Props(), which is equivalent to Props[Nothing],
which is equivalent to «bug»
- add test case which verifies that context.actorOf is still synchronous
- plus all the stuff I have forgotten.
- extend systemDrain to take the new contents which shall be switched in
- make NoMessage placeholder which will signal final closing of the
mailbox
- put that in when cleaning up, and check it when enqueuing
- replace TreeMap with custom ChildrenContainer, which has three
implementations: empty, normal and “terminating” (i.e. waiting for
some child to terminate)
- split recreate() in the same way as terminate(), so that there is a
phase during which the suspended actor waits for termination of all
children which were stopped in preRestart
- do not null out “actor” in ActorCell during restart, because we do
need the supervisionStrategy and nulling it out does not buy us much
in this case anyway
- provide new ActorContext.suspendForChildTermination(), which enters
limbo for as long there are outstanding termination requests; this
enables code which is very similar to previously (half-working) setups
with “synchronous” context.stop(child)
docs are still missing, plus a little polishing here and there; oh, and
before I forget: ActorCell NOW is 64 bytes again ;-)
- this enables using any MessageQueue in BalancingDispatcher,
CallingThreadDispatcher and in general leads to less conflation of
concepts
- add MessageQueue.cleanUp(owner, deadLetterQueue) for the benefit of
durable mailboxes
- change MailboxType.create to take an optional owner and generate only
a MessageQueue, not a Mailbox
- change from messageQueue.numberOfMessages to maintaining an AtomicLong
for performance reasons
- add comments/scaladoc where missing
- remove some assert()s
- fix ResiserSpec to employ buddy-wakeup-threshold
- first, fix quite some data races in RoutedActorRef wrt. the contained
ActorCell’s childrenRef field (which is not even @volatile)
- then notice that there still are double-deregistrations happening in
the dispatcher
- coming finally to the conclusion that the Mailbox should not really
process all system messages in processAllSystemMessages(): we should
really really stop after having closed the mailbox ;-)
- added simple test case which stops self twice to keep this fixed