diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2018-11-21 23:19:32 +0100 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2019-05-13 20:26:45 +0200 |
| commit | ff49cd6c9079264e04d2efa85b03a024d0e00cca (patch) | |
| tree | bc925038f730e784c7d8ed3c0cbe0e07178b0417 /odcsim-engine-omega/src | |
| parent | e1530fee893b5e9ceebf5e07b490c1c82da2e687 (diff) | |
feat: Add consistent exception handling in actor systems
This change makes exception handling in actor systems consistent.
Implementors should not propagate unhandled exceptions in actors to the
(one of the) threads running the engine, but instead should stop the
offending actor and continue running.
Supervision of actors should be implemented within actor behavior
instead. Since BehaviorInterpreter will propagate exceptions thrown by
an actor, consumers of that API can use it to catch unhandled exceptions in an
actor.
Diffstat (limited to 'odcsim-engine-omega/src')
| -rw-r--r-- | odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt b/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt index 56e3020f..c4a9b35f 100644 --- a/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt +++ b/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt @@ -35,6 +35,7 @@ import com.atlarge.odcsim.PostStop import com.atlarge.odcsim.PreStart import com.atlarge.odcsim.Signal import com.atlarge.odcsim.internal.BehaviorInterpreter +import mu.KotlinLogging import java.util.PriorityQueue import kotlin.math.max @@ -75,6 +76,11 @@ class OmegaActorSystem<in T : Any>(root: Behavior<T>, override val name: String) */ private val registry: MutableMap<ActorPath, Actor<*>> = HashMap() + /** + * A [KotlinLogging] instance that writes logs to a SLF4J implementation. + */ + private val logger = KotlinLogging.logger {} + init { registry[path] = Actor(this, root) schedule(this, PreStart, .0) @@ -100,8 +106,16 @@ class OmegaActorSystem<in T : Any>(root: Behavior<T>, override val name: String) time = delivery queue.poll() - // Notice that messages for unknown/terminated actors are ignored for now - registry[envelope.destination]?.interpretMessage(envelope.message) + val actor = registry[envelope.destination] ?: continue + try { + // Notice that messages for unknown/terminated actors are ignored for now + actor.interpretMessage(envelope.message) + } catch (e: Exception) { + // Forcefully stop the actor if it crashed + actor.stop() + + logger.error(e) { "Unhandled exception in actor ${envelope.destination}" } + } } // Jump forward in time as the caller expects the system to have run until the specified instant @@ -171,7 +185,7 @@ class OmegaActorSystem<in T : Any>(root: Behavior<T>, override val name: String) * Terminate this actor and its children. */ fun terminate() { - children.forEach { it.terminate() } + children.forEach { it.stop() } registry.remove(self.path) } |
