docs: correct timeout and blocking-call documentation; harden derive macro paths - #126
Merged
Merged
Conversation
…macro paths - Document that ask timeouts do not cancel admitted messages; retry only idempotent messages, and give tell timeouts their own error suggestions - Clarify blocking_* self-call behavior with a timeout (stall, then Timeout) - Fix wait_stopped docs on ref-drop termination and on_stop reachability - Use fully qualified ::rsactor/::core paths in derive macro expansions - Validate handler receivers by type so self: &mut Self is accepted and by-value mut self is rejected - Fix handler.rs doc example that moved actor_b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A review pass over
src/andrsactor-derive/found documentation that contradicts what the code does, and two hygiene/validation gaps in the derive macros. Behaviour of the library itself is unchanged; the derive changes alter which handler signatures compile.Timeouts can run a handler twice
ask_timeout_innerandask_priority_innerwrap admission and the reply wait in a singletokio::time::timeout. The runtime loop does not check the reply sender'sis_closed()before dispatching an envelope (that check exists only in the shutdown drain), so a deadline that expires after admission leaves the handler running and only discards the reply.Error::is_retryablenevertheless listed ask-sideTimeoutas retryable with no caveat. Changes insrc/error.rsandsrc/actor_ref.rs:is_retryabledocs: an ask-sideTimeoutmeans the original request may still be running or already finished — retry only idempotent messages. A tell-sideTimeoutmeans admission failed, so resending cannot run the handler twice.ask_with_timeout/ask_priority: state that the timeout ends the caller's wait only.debugging_tips: tell-side timeouts (Tell,TellPriority,BlockingTell,BlockingTellPriority) get their own arm. They previously received "use tell instead", which is meaningless for atell.is_retryableexample retried ontell, which never returns a retryable error (it awaits capacity and fails only withError::Send), so the retry branch was unreachable. It now usestell_with_timeout.The return value of
is_retryableis unchanged; changing the dispatch path would not help an already-running handler anyway.Blocking calls and
wait_stoppedblocking_tell_priority/blocking_ask_prioritywarned of an "unrecoverable hang" when called from the actor's own handler. Theirtimeoutis mandatory and bounds the wait, so the loop stalls fortimeoutand the call returnsError::Timeout.blocking_tell/blocking_asknow separatetimeout: None(permanent hang) fromSome(timeout).wait_stopped(&self)holds a strong reference, so it keeps the actor alive against ref-drop termination; the first sentence said the opposite. "(afteron_stopran)" is narrowed:sender.closed()also resolves on theon_start-failure and panic-unwind paths, whereon_stopdoes not run.Derive macros (
rsactor-derive)receiver.mutabilityis themuttoken, so by-valuemut selfpassed andself: &mut Selfwas rejected. The check now inspectsreceiver.tyfor a&mutreference. Verified in a probe crate:self: &mut Selfcompiles and runs;mut selfis rejected at the receiver span.::rsactor::Actor,::rsactor::ActorRef,::rsactor::Message,::rsactor::__log_handler_error,::core::result::Result::{Ok, Err},::core::convert::Infallibleand::core::any::type_name. Verified in a probe crate that both#[derive(Actor)]and#[message_handlers]compile in a scope containingmod rsactor {}anduse Shadow::*(a local enum withOk/Errvariants).Other
src/handler.rsmodule example movedactor_binto.into()and then used it (E0382). It now converts a clone, keeping both theFrom<&ActorRef<T>>andFrom<ActorRef<T>>examples.Verification
cargo fmt --checkcargo clippy --all-targets --all-features -- -D warningscargo test --workspace --all-featuresRUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-featuresLimits
package = "rsactor"under another name) still breaks the::rsactorpaths. Supporting it needsproc-macro-crate, which is a separate decision.self: &mut Box<Self>passes validation and fails later with E0599;&mut ActorRef<Self>, which fails later with E0308;TellPriority, whose slot is fixed at 1;current_threadruntime the call panics and the actor terminates.mainby feat(logging): addlogfeature bridging tracing events to the log crate #123.🤖 Generated with Claude Code