NAME
Acme::Parataxis::Error - Base Class and Diagnostics for Interrupted Fiber Waits
SYNOPSIS
use v5.40;
use Acme::Parataxis qw[async with_timeout];
async {
my $err = do {
eval { with_timeout( 250, sub { $slow_task->run } ) };
$@;
};
if ( ref $err && $err->isa('Acme::Parataxis::Error') ) {
say "Kind: " . $err->kind; # 'timeout'
say "Message: " . $err->message; # "The operation timed out at ..."
say "Interrupted: " . $err->wait_reason->[0]; # 'await_sleep', 'Semaphore down', etc.
say "Stringified: $err"; # stringifies to ->message
}
elsif ($err) {
die $err; # real runtime bug; not an interruption
}
};
DESCRIPTION
Parataxis throws specialized error objects whenever a parked wait is interrupted by a deadline, an explicit cancellation token, or a nursery sibling failure. All such errors descend from Acme::Parataxis::Error.
A single $err->isa('Acme::Parataxis::Error') check cleanly separates expected flow-control cancellations from real application bugs. Standard runtime errors (plain string dies or non-Parataxis exception objects) are never swallowed or converted; they propagate unmodified.
Key characteristics:
Clean interruption point: The exception is thrown at the exact re-entry point of the interrupted wait. The operation being waited on does not half-execute—it is aborted cleanly.
Transparent stringification: All error subclasses overload
""to returnmessage(), allowing them to interpolate naturally in logs, test assertions, and diagnostic warnings.Rich wait metadata: The
wait_reason()accessor exposes where and why the fiber was parked when interrupted, including call-site file, line, and execution backtraces.
The base class is an abstract parent and cannot be instantiated directly. All subclasses reside within this package file; there are no separate .pm files to load.
METHODS
message( )
say $err->message;
# "The operation timed out at Semaphore down (t/worker.pl line 42)"
Returns the formatted diagnostic message containing the failure label and the wait site where the fiber was parked.
kind( )
if ( $err->kind eq 'timeout' ) { ... }
Machine-readable discriminator. Returns one of:
'cancelled'- explicit cancellation token was triggered.'timeout'- awith_timeoutdeadline expired.'nursery'- one or more sibling fibers died inside a nursery.'supervisor'- a supervisor tree exhausted its restart budget.'stm_retry'- internal control-flow signal used by STM transactions (never escapesatomically).
wait_reason( )
my ( $reason, $file, $line, $backtrace ) = @{ $err->wait_reason };
Returns the wait metadata recorded when the fiber parked:
$reason- descriptive string (e.g.'await_sleep','Channel get','Semaphore down').$file- filename where the wait was entered.$line- source line number.$backtrace- arrayref of[ $pkg, $file, $line, $sub ]caller frames leading back to the fiber body.
May be undef for errors that did not originate from a parked wait (e.g. nursery aggregate errors).
SUBCLASSES
Acme::Parataxis::Error::Cancelled
Thrown when an explicit Acme::Parataxis::CancellationToken is cancelled while a fiber is waiting.
->kindreturns'cancelled'.Message format:
"The operation was cancelled at <site">.Supports
->new( wait_reason => $reason )and->throw( ... ).
Acme::Parataxis::Error::Timeout
Thrown when a with_timeout deadline expires before the enclosed block completes.
->kindreturns'timeout'.Message format:
"The operation timed out at <site">.Error::Timeoutis a sibling ofError::Cancelled, not a subclass. Do not useisato tell them apart; switch on->kind.
Acme::Parataxis::Error::Nursery
Thrown by nursery when one or more enrolled child fibers die.
->kindreturns'nursery'.->primary: Returns the first natural failure (the non-cancellation exception that caused the nursery to abort, rather than the cancelled sibling unwinds).->failures: Returns the list of every child exception in enrollment order.
Acme::Parataxis::Error::Supervisor
Thrown by an Acme::Parataxis::Supervisor when a supervised subtree exhausts its allocated restart budget.
->kindreturns'supervisor'.->child: Returns the name of the child whose death exhausted the budget.->primary: Returns the exception that triggered the final failed restart.->failures: Returns every error that counted against the restart budget during the tracking window.
Acme::Parataxis::Error::STM_Retry
Internal control-flow exception thrown by retry() inside an atomically block. Caught internally by the STM engine to roll back speculative writes, park on the transaction's read set, and retry. Never escapes atomically.
Recipes
Differentiating cancellations from timeouts and runtime errors
use v5.40;
use Acme::Parataxis qw[async with_timeout];
async {
my $res = eval {
with_timeout( 5000, $cancel_token, sub {
fetch_remote_resource();
} );
};
my $err = $@;
if ( ref $err && $err->isa('Acme::Parataxis::Error') ) {
if ( $err->kind eq 'timeout' ) { warn "Request timed out after 5s; retrying..." }
elsif ( $err->kind eq 'cancelled' ) { warn "Request explicitly cancelled by caller" }
}
elsif ($err) {
die "Unexpected application failure: $err";
}
};
Extracting root failures from a broken nursery
my $err = do {
eval {
nursery( sub ($n) {
$n->spawn( sub { query_db() } );
$n->spawn( sub { ping_peer() } );
} );
};
$@;
};
if ( ref $err && $err->isa('Acme::Parataxis::Error::Nursery') ) {
my $cause = $err->primary; # the real culprit, skipping sibling cancellations
warn "Nursery failed due to: " . ( ref $cause ? $cause->message : $cause );
# Detailed breakdown of all children:
for my $child_err ( $err->failures ) {
warn " Child error: " . ( ref $child_err ? $child_err->message : $child_err );
}
}
Behavior Notes
__DIE__ hooks fire at every unwinding scope
Parataxis rethrows exceptions across scope boundaries (e.g. from the park re-entry, through the fiber envelope, across await, and out of with_timeout). If a global $SIG{__DIE__} handler is installed, it will fire on each internal rethrow.
When implementing process-wide error logging, filter on isa('Acme::Parataxis::Error') and deduplicate based on "$err":
my %seen_errors;
$SIG{__DIE__} = sub ($err) {
return unless ref $err && $err->isa('Acme::Parataxis::Error');
my $key = "$err";
return if $seen_errors{$key}++;
warn "Parataxis wait interrupted: $err\n";
};
Nursery vs. Supervisor primary resolution
Acme::Parataxis::Error::Nursery filters its failure list: ->primary skips sibling cancellation errors and picks the first true failure.
Acme::Parataxis::Error::Supervisor selects the first defined entry in its failure history, which may be a cancellation if a child was shut down manually. When diagnosing supervisor budget exhaustion, inspect ->failures directly.
SEE ALSO
Acme::Parataxis, Acme::Parataxis::CancellationToken, Acme::Parataxis::Nursery, Acme::Parataxis::Supervisor
AUTHOR
Sanko Robinson https://github.com/sanko
LICENSE
Copyright (C) Sanko Robinson.
This library is free software; you can redistribute it and/or modify it under the terms found in the Artistic License 2.