Skip to content

Make managing actor selector less error prone #95

@ryanmiville

Description

@ryanmiville

I find myself always needing to include my Selector in my actor’s state for any non-trivial actor, or even for trivial actors that are under a supervisor. This feels like I’m carrying around an implementation detail.

Aside from it being cumbersome, I am frequently making mistakes that the compiler can’t catch. It is very easy to accidentally orphan a Subject for your actor if you forget to pass your selector forward on a branch.

Possible Solution

Add a way to merge new selectors into the actor’s current selector. Users won’t need to worry about managing their selectors manually.

Design 1: Add a new Next variant

pub type Next(message, state) {   
  Continue(state: state, selector: Option(Selector(message)))
  AddSelector(state: state: selector: Selector(message))
  Stop(ExitReason) 
}     

then merge it with the existing one in actor.loop. Avoids any breaking changes, but feels janky.

Design 2: Make a breaking change to Next

This is effectively the same idea, but I prefer this because it models things better.

pub opaque type NextSelector(message) {   
  SameSelector   
  AddSelector(Selector(message))   
  ReplaceSelector(Selector(message)) 
}  

pub type Next(message, state) {   
  Continue(state: state, selector: NextSelector(message))
  Stop(ExitReason) 
}    

Example usage

No need to store selector in state, and hard to accidentally orphan subjects.

fn my_actor_loop(message: Message, state: State) {
  case message {
    CallAnotherActor -> {
      let selector = call_another_actor()
      actor.continue(state) |> actor.add_selector(selector)
    }

    OtherActorResponse(_) -> actor.continue(state)

    StartChild -> {
      let assert Ok(child) = actor.start(child_spec())
      let selector = monitor_child(child)
      actor.continue(state) |> actor.add_selector(selector)
    }

    ChildDown(_) -> actor.continue(state)
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions