Skip to main content

Configuration reference

This page documents every configuration value object in Nexus: MailboxConfig, OverflowStrategy, SupervisionStrategy, WorkerPoolConfig, SwooleConfig, ReceiverActorConfig, LifecycleThresholds, ReplyQueueLifecycle, and AskSupport.

MailboxConfig

MailboxConfig is an immutable value object that controls the capacity and overflow policy of an actor's mailbox. Pass it to Props::withMailbox() before spawning an actor.

src/Actor/OrderActor.php
use Monadial\Nexus\Core\Actor\Props;
use Monadial\Nexus\Runtime\Mailbox\MailboxConfig;
use Monadial\Nexus\Runtime\Mailbox\OverflowStrategy;

$props = Props::fromBehavior($behavior)
->withMailbox(MailboxConfig::bounded(500, OverflowStrategy::Backpressure));

Named constructors

MethodParametersDescription
MailboxConfig::bounded(int $capacity, OverflowStrategy $strategy)$capacity — maximum queue depth; $strategy — what happens when fullCreate a bounded mailbox. Default strategy: ThrowException.
MailboxConfig::unbounded()Create an unbounded mailbox. Queue grows without limit.

Modifier methods

MethodReturnsDescription
withCapacity(int $capacity)MailboxConfigReturn a new config with the given capacity.
withStrategy(OverflowStrategy $strategy)MailboxConfigReturn a new config with the given overflow strategy.

Parameters

PropertyTypeDescription
$capacityintMaximum number of enqueued messages. PHP_INT_MAX for unbounded.
$strategyOverflowStrategyPolicy applied when the mailbox is full (bounded only).
$boundedbooltrue for bounded; false for unbounded.

OverflowStrategy

OverflowStrategy is a backed enum that controls what happens when a bounded mailbox is at capacity and a new message arrives.

CaseValueBehaviour
DropNewestdrop_newestSilently discard the incoming message. The mailbox keeps all existing messages.
DropOldestdrop_oldestSilently discard the oldest message in the queue to make room.
BackpressurebackpressureSuspend the sending fiber until space is available.
ThrowExceptionthrow_exceptionThrow MailboxOverflowException at the call site of tell(). Default.
src/Actor/Pipeline.php
use Monadial\Nexus\Runtime\Mailbox\MailboxConfig;
use Monadial\Nexus\Runtime\Mailbox\OverflowStrategy;

// Circuit-breaker: reject excess messages immediately
$props = Props::fromBehavior($behavior)
->withMailbox(MailboxConfig::bounded(200, OverflowStrategy::ThrowException));

// Rate-limit producers: block sender fiber until mailbox drains
$props = Props::fromBehavior($behavior)
->withMailbox(MailboxConfig::bounded(200, OverflowStrategy::Backpressure));
Backpressure holds the sender's fiber

OverflowStrategy::Backpressure suspends the calling fiber until the mailbox has room. If the mailbox never drains, the sender hangs indefinitely. Apply a send timeout at the application level when using this strategy in pipelines.


SupervisionStrategy

SupervisionStrategy is an immutable value object attached to Props via Props::withSupervision(). It determines what the parent actor does when a child throws an unhandled exception.

The decider is a Closure(Throwable): Directive that maps each exception type to one of four directives: Directive::Restart, Directive::Stop, Directive::Resume, or Directive::Escalate.

SupervisionStrategy::oneForOne

Only the failed child is acted upon. Other children continue processing.

src/Actor/OrderSupervisor.php
use Monadial\Nexus\Core\Actor\Props;
use Monadial\Nexus\Core\Supervision\Directive;
use Monadial\Nexus\Core\Supervision\SupervisionStrategy;
use Monadial\Nexus\Runtime\Duration;

$props = Props::fromBehavior($behavior)->withSupervision(
SupervisionStrategy::oneForOne(
maxRetries: 5,
window: Duration::seconds(30),
decider: static fn(\Throwable $e): Directive => $e instanceof \RuntimeException
? Directive::Restart
: Directive::Stop,
),
);
ParameterTypeDefaultDescription
$maxRetriesint3Maximum restart attempts within $window before the child is stopped.
$windowDuration|nullDuration::seconds(60)Rolling time window for counting restarts.
$deciderClosure(Throwable): Directive|nullDirective::Restart for allMaps each exception to a directive.

SupervisionStrategy::allForOne

When one child fails, all children are acted upon by the same directive.

src/Actor/ClusterSupervisor.php
use Monadial\Nexus\Core\Supervision\SupervisionStrategy;
use Monadial\Nexus\Runtime\Duration;

$strategy = SupervisionStrategy::allForOne(
maxRetries: 3,
window: Duration::seconds(60),
);

Parameters are identical to oneForOne.

SupervisionStrategy::exponentialBackoff

Restarts the failed child with increasing delay between attempts. Use when the failure is likely transient and immediate restart would cause a thundering-herd problem.

src/Actor/DbActor.php
use Monadial\Nexus\Core\Supervision\SupervisionStrategy;
use Monadial\Nexus\Runtime\Duration;

$strategy = SupervisionStrategy::exponentialBackoff(
initialBackoff: Duration::millis(100),
maxBackoff: Duration::seconds(30),
maxRetries: 10,
multiplier: 2.0,
);
ParameterTypeDefaultDescription
$initialBackoffDurationDelay before the first restart attempt.
$maxBackoffDurationUpper bound on the delay; subsequent attempts are capped here.
$maxRetriesint3Maximum number of restart attempts total.
$multiplierfloat2.0Factor applied to $initialBackoff on each retry.
$deciderClosure(Throwable): Directive|nullDirective::Restart for allMaps each exception to a directive.

WorkerPoolConfig

WorkerPoolConfig configures the Swoole thread pool used by the worker-pool package. Call WorkerPoolApp::run(WorkerPoolConfig) with this value.

src/WorkerPool/MyPoolApp.php
use Monadial\Nexus\WorkerPool\WorkerPoolConfig;

WorkerPoolConfig::withThreads(8);
MethodParameterDescription
WorkerPoolConfig::withThreads(int $workerCount)$workerCount ≥ 1Create a config for N worker threads. Throws InvalidArgumentException if $workerCount < 1.
withSystemNamePrefix(string $prefix)Any non-empty stringOverride the default 'worker' prefix used for internal actor system names.

SwooleConfig

SwooleConfig tunes the Swoole runtime. Pass it to SwooleRuntime::__construct().

src/bootstrap.php
use Monadial\Nexus\Runtime\Swoole\SwooleConfig;
use Monadial\Nexus\Runtime\Swoole\SwooleRuntime;

$runtime = new SwooleRuntime(
new SwooleConfig(
defaultMailboxCapacity: 5000,
enableCoroutineHook: true,
maxCoroutines: 200_000,
),
);
ParameterTypeDefaultDescription
$defaultMailboxCapacityint1000Default channel size for actor mailboxes created by the Swoole runtime.
$enableCoroutineHookbooltrueEnable Swoole's coroutine hooks to make blocking I/O non-blocking inside coroutines.
$maxCoroutinesint100_000Maximum concurrent coroutines allowed in the Swoole event loop.

Modifier methods

MethodDescription
withDefaultMailboxCapacity(int $capacity)Return a new config with the given mailbox capacity.
withEnableCoroutineHook(bool $enable)Return a new config with coroutine hooking on or off.
withMaxCoroutines(int $max)Return a new config with the given coroutine ceiling.

ReceiverActorConfig

ReceiverActorConfig is an immutable value object that tunes the ReceiverActor poll loop. Obtain the default with ReceiverActorConfig::default() and chain wither methods for overrides.

src/bootstrap.php
use Monadial\Nexus\Messenger\Consumer\ReceiverActorConfig;
use Monadial\Nexus\Messenger\Consumer\UnroutablePolicy;
use Monadial\Nexus\Runtime\Duration;

$config = ReceiverActorConfig::default()
->withPollInterval(Duration::millis(50))
->withUnroutablePolicy(UnroutablePolicy::DeadLetters);

Named constructors

MethodDescription
ReceiverActorConfig::default()pollInterval = 100 ms, unroutablePolicy = Reject, askPendingTimeout = 30 s, maxPendingAsks = 1024.

Modifier methods

MethodReturnsDescription
withPollInterval(Duration $pollInterval)ReceiverActorConfigOverride how long the actor waits before the next poll when idle or backpressured.
withUnroutablePolicy(UnroutablePolicy $policy)ReceiverActorConfigOverride what happens to messages that MessageRouter::route() returns null for.
withAskPendingTimeout(Duration $timeout)ReceiverActorConfigOverride the deadline after which an un-answered ask envelope is rejected for redelivery.
withMaxPendingAsks(int $max)ReceiverActorConfigOverride the cap on concurrently pending asks. Must be a positive integer (throws InvalidArgumentException otherwise).

Parameters

PropertyTypeDefaultDescription
$pollIntervalDurationDuration::millis(100)Wait between idle or backpressured poll ticks. Busy ticks re-poll immediately.
$unroutablePolicyUnroutablePolicyUnroutablePolicy::RejectReject — reject back to transport; DeadLetters — forward to the dead-letters ref and ack.
$askPendingTimeoutDurationDuration::seconds(30)How long the receiver holds a broker envelope un-acked while waiting for the responder actor to publish a reply. When the deadline passes, the envelope is rejected for redelivery and nexus.messenger.asks.responder_expired is incremented.
$maxPendingAsksint1024Cap on the number of unanswered ask envelopes held in memory at once. Once reached, a new ask is shed — rejected for broker redelivery instead of being tracked — and nexus.messenger.asks.shed is incremented, so a producer flooding asks cannot grow the pending map without bound. The live pending count is exposed as the nexus.messenger.asks.pending gauge.

ReplyQueueLifecycle

ReplyQueueLifecycle is a pure enum that controls how the reply queue behind a TransportReplyChannelFactory is created and torn down.

CaseQueue created by NexusQueue torn down by NexusNotes
EphemeralYes — on the first ask callNo — left to the broker (TTL / auto-delete)Default. Requires the broker to support per-queue TTL or auto-delete.
DeleteOnShutdownYes — on the first ask callBest-effort via reset() on AskSupport::close()Broker-side TTL is the authoritative backstop; reset() only resets connection state, it does not delete the queue.
PersistentNo — externally pre-provisionedNeverUse for SQS and brokers where queue creation is slow or costly. Warning: all instances that share the queue name compete for replies. Use only one consumer per channel name. The DSN template must not contain {instance}.
use Monadial\Nexus\Messenger\Ask\ReplyQueueLifecycle;
use Monadial\Nexus\Messenger\Ask\TransportReplyChannelFactory;

$factory = new TransportReplyChannelFactory(
$transportFactory,
$serializer,
'amqp://broker/replies-{name}-{instance}?queue[ttl]=300000',
'orders-replies',
ReplyQueueLifecycle::Ephemeral, // or DeleteOnShutdown, Persistent
);

AskSupport

AskSupport coordinates broker ask/reply on the asker side: it lazily creates the reply channel, spawns the nexus-ask-replies consumer actor, registers pending ask futures, and schedules timeouts. The idiomatic way to build one is MessengerBridge::askSupport().

src/bootstrap.php
use Monadial\Nexus\Messenger\MessengerBridge;
use Monadial\Nexus\Runtime\Duration;

$askSupport = MessengerBridge::askSupport(
system: $system,
factory: $channelFactory,
maxPending: 5_000, // optional; default 10 000
replyPollInterval: Duration::millis(10), // optional; default 20 ms
observability: $observability, // optional; default NoopObservability
events: $eventDispatcher, // optional; default null
);

$ref = MessengerBridge::producer($transport, 'orders-out', askSupport: $askSupport);

MessengerBridge::askSupport() parameters

ParameterTypeDefaultDescription
$systemActorSystemThe actor system; used to spawn the nexus-ask-replies consumer and schedule timeouts.
$factoryReplyChannelFactoryFactory that creates the reply transport channel. Typically a TransportReplyChannelFactory.
$maxPending?int10 000Maximum number of concurrent in-flight asks. When reached, ask() throws AskCapacityExceededException immediately.
$replyPollInterval?DurationDuration::millis(20)How often the ReplyConsumer actor polls the reply channel when idle. Busy ticks (replies found) re-poll immediately.
$observabilityObservabilityNoopObservabilityOTel instrumentation for ask metrics and spans.
$events?EventDispatcherInterfacenullPSR-14 dispatcher for AskStarted, AskResolved, AskTimedOut, and ReplyPublished events.

AskSupport methods

MethodDescription
replyChannelName(): stringReturn the logical reply channel name, lazily creating the channel and spawning the consumer actor on the first call. Idempotent.
ask(Duration $timeout, string $correlationId): FutureRegister a pending ask and schedule its timeout. Throws AskCapacityExceededException at capacity.
registry(): PendingAskRegistryAccess the underlying pending-ask registry (for monitoring or testing).
close(): voidRelease the reply channel. Call during ActorSystem shutdown to release transport resources.

LifecycleThresholds

LifecycleThresholds is an immutable value object evaluated by LifecycleWatchdog on each tick. A null limit is disabled. All comparisons are inclusive: reaching the limit exactly triggers a breach.

src/bootstrap.php
use Monadial\Nexus\Messenger\Lifecycle\LifecycleThresholds;
use Monadial\Nexus\Runtime\Duration;

$thresholds = LifecycleThresholds::none()
->withMessageLimit(10_000)
->withMemoryLimit(128 * 1024 * 1024)
->withTimeLimit(Duration::seconds(3600));

Named constructors

MethodDescription
LifecycleThresholds::none()All three limits disabled (null).

Modifier methods

MethodParameterDescription
withMemoryLimit(int $bytes)BytesBreach when memory_get_usage(true) >= $bytes.
withMessageLimit(int $count)CountBreach when cumulative processed messages >= $count.
withTimeLimit(Duration $limit)DurationBreach when actor uptime >= the limit (second precision).

Parameters

PropertyTypeDefaultDescription
$memoryLimitBytes?intnullMemory threshold in bytes; null = disabled.
$messageLimit?intnullCumulative message count threshold; null = disabled.
$timeLimit?DurationnullUptime threshold; null = disabled.

LifecycleWatchdog defaults

When LifecycleWatchdog::create() is called without explicit timing parameters, the watchdog uses:

ParameterDefault
$checkIntervalDuration::seconds(5)
$shutdownTimeoutDuration::seconds(10)

See also