drama
drama copied to clipboard
Ideas and inspiration
Todo
- [ ] Document concurrency / supervision / process tree semantics
- When a parent actor dies, it's children get killed
- When a child actor dies, it throws to the parent
- These aren't necessarily the semantics I want
Exceptions thoughts
- Actors should only have one way of communicating: via messages
- Exceptions are another way actors get to communicate in
drama
, but that violates the actor model - Child death should be a message
- Parent suicide upon child death should be handled by a higher-level supervision-style wrapper around the base actor, and should be triggered by message
- Synchronous exceptions should never escape the current actor/thread, except via a message
- Asynchronous exceptions should be treated as unrecoverable panics, and can override the previous rule by default
Ideas
- Use bounded channels from
unagi-chan
- Re-implement in terms of
async
function fromunliftio
, and hope addingbracket
s makes it just as safe? Would allowMonadUnliftIO
stuff. - Supervisor stuff?
- Add
isAlive
andkill
/stop
functions (finally
write to someMVar
or something to indicate death? OrtakeMVar
to pull the rug out from under a process?)
Inspiration
-
- Uses a dynamic message type, akin to the
Handler
type fromControl.Exception
used for handling different types of exceptions.
- Uses a dynamic message type, akin to the
-
- Has a
respond
function that returns aResponded
type, which means the compiler can verify that an actor responds to a message. - Message recipients can be provided a function for responding, encoded in the
Responder
type (wrapper arounda -> IO ()
).
- Has a
-
https://ryhl.io/blog/actors-with-tokio/
-
https://crates.io/crates/actix
-
https://hackage.haskell.org/package/open-union: Infix operator for
decomp
osing unions, kinda likecase union of
or something. Final null case could be made unnecessary by making the operator a type class method.
Spawning and exception handling
Indeed, making a distinction between (in Erlang vocabulary) spawn
, spawn_link
and spawn_monitor
would be good. At that point, the question becomes whether using Ki and its scoped threads makes sense.
A difficulty might be modeling the messages being used: currently, it's up to the consumer of drama
to define all message types. If the internals would also use messages to get things done, there'd either be the need for extensible types (a-la open-union
, but that pushes quite some burden on the user of the library), or wrapping "user" messages in something which can also contain "system" messages, and dispatching within the library code.
Base monads
Did you ever consider turning Actor
into a transformer? While using drama
, I frequently wished for there to be some Reader(T)
environment to be available. Similarly, I wish I could turn an Actor
into a MonadLogger
(with an instance in the stack which routes all log messages to some Logger
actor). Neither of those are currently possible.
Operations in Actor
(like spawn
, receive
,...) should then ideally be defined in some class, so they can be lifted: right now, using Actor
as a base monad in a stack doesn't really work either: once inside a lift receive _
, there's no more access to the stacked effects.
So maybe instead of turning Actor
into a transformer, making the (core) actor actions classy would help, at which point instances for ReaderT
, LoggingT
and whatever else could be provided.