or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

actor-system.mdactors-props.mdfsm.mdindex.mdmessaging-references.mdpatterns-utilities.mdscheduling-timers.mdsupervision.md
tile.json

messaging-references.mddocs/

Messaging and References

ActorRef provides location-transparent references to actors with immutable message passing, while ActorSelection enables pattern-based actor lookup and communication.

Capabilities

Actor References

Immutable, serializable handles to actors supporting location-transparent message passing.

/**
 * Immutable reference to an actor, local or remote
 */
abstract class ActorRef extends java.lang.Comparable[ActorRef] with Serializable {
  /**
   * Send message with fire-and-forget semantics (Scala API)
   * @param message - Message to send
   * @param sender - Implicit sender reference
   */
  def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit
  
  /**
   * Send message with explicit sender (Java API)
   * @param msg - Message to send
   * @param sender - Sender reference
   */
  def tell(msg: Any, sender: ActorRef): Unit
  
  /**
   * Forward message preserving original sender
   * @param message - Message to forward
   * @param context - Implicit actor context
   */
  def forward(message: Any)(implicit context: ActorContext): Unit
  
  /**
   * Hierarchical path to this actor
   */
  def path: ActorPath
  
  /**
   * Compare actors by path and unique identifier
   * @param other - ActorRef to compare with
   * @return Comparison result
   */
  final def compareTo(other: ActorRef): Int
}

object ActorRef {
  /**
   * Sentinel value for no sender
   */
  final val noSender: ActorRef = Actor.noSender
}

Usage Examples:

import akka.actor._

// Send messages
val actorRef: ActorRef = system.actorOf(Props[MyActor])

// Fire-and-forget
actorRef ! "hello"

// With explicit sender (from within actor)
class SenderActor extends Actor {
  def receive = {
    case "forward" => 
      actorRef.tell("forwarded message", self)
    case "relay" =>
      actorRef.forward("relayed message")
  }
}

// Path access
println(s"Actor path: ${actorRef.path}")
println(s"Actor name: ${actorRef.path.name}")

Actor Paths

Hierarchical addressing system for actors with support for relative and absolute paths.

/**
 * Hierarchical path uniquely identifying an actor
 */
sealed trait ActorPath extends Comparable[ActorPath] {
  /**
   * Actor system address
   */
  def address: Address
  
  /**
   * Path elements from root to this actor
   */
  def elements: immutable.Iterable[String]
  
  /**
   * Actor name (last element of path)
   */
  def name: String
  
  /**
   * Parent path (all but last element)
   */
  def parent: ActorPath
  
  /**
   * Root path of the actor system
   */
  def root: RootActorPath
  
  /**
   * Create child path
   * @param child - Child actor name
   * @return Child actor path
   */
  def /(child: String): ActorPath
  
  /**
   * Create descendant path from sequence
   * @param children - Sequence of child names
   * @return Descendant actor path
   */
  def /(children: Iterable[String]): ActorPath
  
  /**
   * Unique identifier for this actor instance
   */
  def uid: Int
  
  /**
   * Convert to string representation
   */
  def toStringWithoutAddress: String
  
  /**
   * Convert to string with address
   */
  override def toString: String
}

/**
 * Root path of actor system
 */
class RootActorPath(val address: Address, val name: String = "/") extends ActorPath

/**
 * Child path within actor hierarchy
 */
class ChildActorPath(val parent: ActorPath, val name: String, val uid: Int) extends ActorPath

Usage Examples:

// Path manipulation
val systemPath = ActorPath.fromString("akka://MySystem@127.0.0.1:2552/")
val userPath = systemPath / "user" 
val childPath = userPath / "myActor"
val descendantPath = systemPath / List("user", "parent", "child")

// Path information
println(s"Actor name: ${childPath.name}")
println(s"Parent path: ${childPath.parent}")
println(s"Full path: ${childPath}")
println(s"Without address: ${childPath.toStringWithoutAddress}")

// Path comparison and equality
val path1 = ActorPath.fromString("akka://System/user/actor")
val path2 = ActorPath.fromString("akka://System/user/actor")
println(s"Paths equal: ${path1 == path2}")

Actor Selection

Pattern-based actor lookup supporting wildcards and path traversal.

/**
 * Selection of actors by path pattern with wildcard support
 */
abstract class ActorSelection {
  /**
   * Send message to all selected actors
   * @param msg - Message to send
   * @param sender - Implicit sender reference
   */
  def !(msg: Any)(implicit sender: ActorRef = Actor.noSender): Unit
  
  /**
   * Send message with explicit sender
   * @param msg - Message to send  
   * @param sender - Sender reference
   */
  def tell(msg: Any, sender: ActorRef): Unit
  
  /**
   * Forward message to selected actors
   * @param msg - Message to forward
   * @param context - Implicit actor context
   */
  def forward(msg: Any)(implicit context: ActorContext): Unit
  
  /**
   * Resolve selection to single ActorRef
   * @param timeout - Resolution timeout
   * @return Future[ActorRef] if single actor found
   * @throws ActorNotFound if no actor or multiple actors found
   */
  def resolveOne()(implicit timeout: Timeout): Future[ActorRef]
  
  /**
   * Path pattern this selection represents
   */
  def pathString: String
  
  /**
   * Anchor ActorRef for relative selections
   */
  def anchor: ActorRef
}

Usage Examples:

import akka.util.Timeout
import scala.concurrent.duration._
import akka.pattern.ask

// Actor selection patterns
val system = ActorSystem("SelectionExample")

// Select by absolute path
val userGuardian = system.actorSelection("/user")
val specificActor = system.actorSelection("/user/myActor")

// Wildcard selections
val allUserChildren = system.actorSelection("/user/*")
val allDescendants = system.actorSelection("/user/**")

// Relative selections (from within actor)
class SelectingActor extends Actor {
  def receive = {
    case "selectSibling" =>
      val sibling = context.actorSelection("../siblingActor")
      sibling ! "hello"
      
    case "selectChild" =>
      val child = context.actorSelection("childActor")
      child ! "message"
      
    case "selectDescendant" =>
      val descendant = context.actorSelection("*/deeply/nested/actor")
      descendant ! "deep message"
  }
}

// Resolve selection to ActorRef
implicit val timeout = Timeout(5.seconds)
val selection = system.actorSelection("/user/myActor")

val futureRef: Future[ActorRef] = selection.resolveOne()
futureRef.onComplete {
  case Success(actorRef) => println(s"Found actor: $actorRef")
  case Failure(exception) => println(s"Actor not found: $exception")
}

// Send to multiple actors via wildcard
system.actorSelection("/user/worker-*") ! "broadcast message"

Actor Context

Actor execution environment providing access to system resources and lifecycle management.

/**
 * Execution context for actor behavior
 */
trait ActorContext extends ActorRefFactory {
  /**
   * Create child actor with generated name
   * @param props - Props for child actor
   * @return ActorRef to child
   */
  def actorOf(props: Props): ActorRef
  
  /**
   * Create named child actor
   * @param props - Props for child actor
   * @param name - Unique child name
   * @return ActorRef to child
   */
  def actorOf(props: Props, name: String): ActorRef
  
  /**
   * Select actors by path pattern
   * @param path - Selection path pattern
   * @return ActorSelection for pattern
   */
  def actorSelection(path: String): ActorSelection
  
  /**
   * Select actors by ActorPath
   * @param path - Structured actor path
   * @return ActorSelection for path
   */
  def actorSelection(path: ActorPath): ActorSelection
  
  /**
   * Stop child actor
   * @param actor - Child ActorRef to stop
   */
  def stop(actor: ActorRef): Unit
  
  /**
   * Watch actor for termination
   * @param actor - ActorRef to watch
   * @return The watched ActorRef
   */
  def watch(actor: ActorRef): ActorRef
  
  /**
   * Stop watching actor
   * @param actor - ActorRef to unwatch
   * @return The unwatched ActorRef
   */
  def unwatch(actor: ActorRef): ActorRef
  
  /**
   * Current child actors
   */
  def children: immutable.Iterable[ActorRef]
  
  /**
   * Get child by name
   * @param name - Child actor name
   * @return Some(ActorRef) if found, None otherwise
   */
  def child(name: String): Option[ActorRef]
  
  /**
   * Reference to this actor
   */
  def self: ActorRef
  
  /**
   * Sender of current message
   */
  def sender(): ActorRef
  
  /**
   * Parent actor reference
   */
  def parent: ActorRef
  
  /**
   * Actor system reference
   */
  def system: ActorSystem
  
  /**
   * Current message dispatcher
   */
  def dispatcher: ExecutionContext
  
  /**
   * Change actor behavior
   * @param behavior - New receive function
   * @param discardOld - Whether to discard current behavior
   */
  def become(behavior: Actor.Receive, discardOld: Boolean = true): Unit
  
  /**
   * Revert to previous behavior
   */
  def unbecome(): Unit
  
  /**
   * Set receive timeout
   * @param timeout - Timeout duration
   */
  def setReceiveTimeout(timeout: Duration): Unit
  
  /**
   * Current receive timeout
   */
  def receiveTimeout: Duration
}

Usage Examples:

class ContextUsingActor extends Actor {
  def receive = {
    case "createChild" =>
      val child = context.actorOf(Props[ChildActor], "child-1")
      sender() ! s"Created child: ${child.path}"
      
    case "listChildren" =>
      val childNames = context.children.map(_.path.name).mkString(", ")
      sender() ! s"Children: $childNames"
      
    case "watchChild" =>
      context.child("child-1") match {
        case Some(child) =>
          context.watch(child)
          sender() ! "Now watching child"
        case None =>
          sender() ! "Child not found"
      }
      
    case "selectSibling" =>
      val sibling = context.actorSelection("../sibling")
      sibling ! "hello from sibling"
      
    case "changeBehavior" =>
      context.become {
        case "reset" => context.unbecome()
        case msg => sender() ! s"New behavior received: $msg"
      }
      
    case "setTimeout" =>
      context.setReceiveTimeout(30.seconds)
      
    case ReceiveTimeout =>
      println("No messages received within timeout period")
  }
}

Types

/**
 * System address for remote communication
 */
case class Address(
  protocol: String,
  system: String,
  host: Option[String] = None,
  port: Option[Int] = None
) {
  def hasGlobalScope: Boolean
  def hasLocalScope: Boolean
  override def toString: String
}

/**
 * Message envelope with sender information
 */
case class Envelope(message: Any, sender: ActorRef) {
  def copy(message: Any = this.message, sender: ActorRef = this.sender): Envelope
}

/**
 * Factory interface for creating actors
 */
trait ActorRefFactory {
  def actorOf(props: Props): ActorRef
  def actorOf(props: Props, name: String): ActorRef
  def stop(actor: ActorRef): Unit
}

/**
 * Serializable actor reference
 */
@SerialVersionUID(1L)
private[akka] final case class SerializedActorRef private (path: String) {
  def this(actorRef: ActorRef)
  def readResolve(): AnyRef
}