Package: groovy.concurrent

## [Java] Interface ActorContext<T>

-     public interface ActorContext<T>

  Context handle passed to context-aware actor handlers. Provides access to the executing actor itself and to the per-dispatch capabilities needed to express FSM-style actors: behavior swaps via become(ReactorHandler) become(...), message deferral via stash() / unstashAll(), and timed self-sends via scheduleOnce(Object, Duration) scheduleOnce(...) / scheduleAtFixedRate(Object, Duration, Duration) scheduleAtFixedRate(...).

  A context is scoped to a single actor and is only valid for use during a handler invocation (including a context-aware `onError` callback). Calls to its mutating methods from outside that window — for example from a captured reference invoked on another thread — throw IllegalStateException.

  Type Parameters:
    `T` - the actor's message type
  See Also:
    Actor
  Since:
    6.0.0

- - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `<R>` | `public void` | `become(ReactorHandler<T, R> newHandler)` Replaces the handler used to process subsequent messages on a reactor actor.
    `<S>` | `public void` | `become(StatefulHandler<S, T> newHandler)` Replaces the handler used to process subsequent messages on a stateful actor.
    `` | `public Cancellable` | `scheduleAtFixedRate(T message, Duration initialDelay, Duration interval)` Schedules a recurring self-send: the given message is delivered to this actor starting after `initialDelay`, then again every `interval` thereafter (fixed-rate).
    `` | `public Cancellable` | `scheduleOnce(T message, Duration delay)` Schedules a one-shot self-send: the given message is delivered to this actor after the given delay, via the same dispatch path as Actor.send (mailbox bound respected, `onError` fires on handler failure, etc.).
    `` | `public Actor<T>` | `self()` Returns the actor whose handler is currently executing.
    `` | `public void` | `stash()` Defers the message currently being processed.
    `` | `public void` | `unstashAll()` Re-injects all stashed messages at the head of the mailbox in the order they were originally stashed (FIFO).

- - ### Method Detail

    - #### <R> public void become(ReactorHandler<T, R> newHandler)

      Replaces the handler used to process subsequent messages on a reactor actor. The swap takes effect on the next message — the current handler invocation completes normally, including binding any `sendAndGet` reply and firing `onError` on failure.

      The new handler may declare a different reply type than the original; `sendAndGet` callers receive the new handler's return value.

      Messages already queued at the moment of the swap, and messages sent by other threads that have not yet observed the swap, are dispatched to the new handler. The new handler is responsible for tolerating any message its predecessor could have received — typically by including a default branch that ignores or rejects unexpected messages, or by deferring them with stash() for later replay.

      throws:
        UnsupportedOperationException if this actor is stateful, or if this `ActorContext` implementation does not support behavior swaps
      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        NullPointerException if `newHandler` is null
      Parameters:
        `newHandler` - the replacement reactor handler
      Type Parameters:
        `R` - the new reactor's reply type
      Since:
        6.0.0

    - #### <S> public void become(StatefulHandler<S, T> newHandler)

      Replaces the handler used to process subsequent messages on a stateful actor. The current state value is preserved verbatim and passed unchanged to the new handler. The swap takes effect on the next message.

      The state type `S` is unchecked at the swap site: if the new handler's expected state type is incompatible with the actor's current state, a ClassCastException is thrown when the next message is dispatched.

      throws:
        UnsupportedOperationException if this actor is a reactor, or if this `ActorContext` implementation does not support behavior swaps
      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        NullPointerException if `newHandler` is null
      Parameters:
        `newHandler` - the replacement stateful handler
      Type Parameters:
        `S` - the state type expected by the new handler
      Since:
        6.0.0

    - #### public Cancellable scheduleAtFixedRate(T message, Duration initialDelay, Duration interval)

      Schedules a recurring self-send: the given message is delivered to this actor starting after `initialDelay`, then again every `interval` thereafter (fixed-rate). Cancellation stops further firings; an already-dispatched message in the mailbox is unaffected.

      Same lifecycle and bounded-mailbox caveats as scheduleOnce(Object, Duration) apply.

      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        NullPointerException if any argument is null
      throws:
        UnsupportedOperationException if this `ActorContext` implementation does not support scheduling
      Parameters:
        `message` - the message to deliver
        `initialDelay` - the wait before the first delivery
        `interval` - the wait between successive deliveries
      Returns:
        a handle for cancelling further firings
      Since:
        6.0.0

    - #### public Cancellable scheduleOnce(T message, Duration delay)

      Schedules a one-shot self-send: the given message is delivered to this actor after the given delay, via the same dispatch path as Actor.send (mailbox bound respected, `onError` fires on handler failure, etc.).

      The returned Cancellable can be used to call off the send before it fires. On Actor.stop, all outstanding scheduled timers (one-shot and recurring) created via this context are cancelled automatically.

      Timer firings race with the actor's lifecycle: a send that arrives after the actor has stopped is silently dropped (the implementation catches the IllegalStateException that `send` would throw). Combining a bounded mailbox using ActorOptions.Overflow#BLOCK with timers is discouraged: each timer firing offloads its `send` to the shared async executor, so the scheduler thread itself never blocks, but a full mailbox will then tie up an executor thread until space frees, and enough such timers can exhaust the shared pool. Prefer ActorOptions.Overflow#FAIL or ActorOptions.Overflow#DROP_NEWEST for actors that schedule their own messages.

      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        NullPointerException if `message` or `delay` is null
      throws:
        UnsupportedOperationException if this `ActorContext` implementation does not support scheduling
      Parameters:
        `message` - the message to deliver
        `delay` - how long to wait before delivering
      Returns:
        a handle for cancelling the scheduled send
      Since:
        6.0.0

    - #### public Actor<T> self()

      Returns the actor whose handler is currently executing.

    - #### public void stash()

      Defers the message currently being processed. The message is moved out of the dispatch path: any `sendAndGet` reply remains unbound, any state change computed by the current handler is discarded, and the message is re-delivered when unstashAll() is later called.

      Calling `stash()` more than once during a single handler invocation is idempotent — the message is stashed once. If the handler subsequently throws, the stash is rolled back and the failure is reported normally (reply bound to error, `onError` fires). A context-aware `onError` callback may itself call `stash()` to defer the failed message for later retry.

      Stashed messages do not count against the configured mailbox bound — the bound applies to the queue of pending sends, not to messages held in the stash.

      Warning — the stash buffer is unbounded by default. An actor that stashes messages from a source whose volume you do not control (network input, external clients, untrusted callers) can grow the stash without limit and exhaust the JVM heap if the phase transition that would call unstashAll() never arrives. For any such actor, configure a bound and overflow policy at construction time via ActorOptions.withStashBound. The three policies are `FAIL` (this method throws), `DROP_OLDEST` (evicts the oldest stashed message, binding its reply to IllegalStateException), and `REJECT` (binds the current message's reply to IllegalStateException and does not stash it).

      If Actor.stop is invoked while messages are stashed, the stashed messages are rejected: any `sendAndGet` reply is bound to an IllegalStateException and fire-and-forget stashed messages are discarded.

      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        UnsupportedOperationException if this `ActorContext` implementation does not support stash
      Since:
        6.0.0

    - #### public void unstashAll()

      Re-injects all stashed messages at the head of the mailbox in the order they were originally stashed (FIFO). Subsequent dispatches will see the unstashed messages before any messages that other senders have queued in the meantime.

      No-op if no messages are stashed.

      throws:
        IllegalStateException if called outside a handler dispatch or from a thread other than the actor's worker thread
      throws:
        UnsupportedOperationException if this `ActorContext` implementation does not support stash
      Since:
        6.0.0