fix: surface actual actor failure instead of generic recv error in collector handles - #53
fix: surface actual actor failure instead of generic recv error in collector handles#53rodonile wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The new early-failure surfacing still leaves a race where send(LocalAddr) failures return generic SendError (and the new ActorFailed variants aren’t exposed via the error chain), which can continue to hide the real startup cause.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR improves startup error reporting for flow-service and udp-notif-service actor handles by detecting when an actor task terminates before it can return its LocalAddr, and by propagating the actor’s real failure (e.g., socket bind errors) instead of a generic channel receive error.
Changes:
- Added
ActorFailed(...)variants to the handle error enums to carry the actor’s startup failure. - Updated
*_Handle::new()totokio::select!between the actorJoinHandleand theLocalAddrreply to detect early termination and surface the underlying error.
File summaries
| File | Description |
|---|---|
| crates/udp-notif-service/src/actor.rs | Adds ActorFailed(UdpNotifActorError) and races join-handle vs. local-addr response during handle creation. |
| crates/flow-service/src/flow_actor.rs | Adds ActorFailed(FlowCollectorActorError) and applies the same early-exit detection during handle creation. |
Review details
Suppressed comments (2)
crates/udp-notif-service/src/actor.rs:1045
- If the actor exits very quickly (e.g. bind() fails), cmd_tx.send(LocalAddr) can also fail with the receiver already dropped, and this path still returns SendError which hides the real cause. Since this PR is about surfacing early actor startup failures, consider awaiting the join handle on send failure and returning ActorFailed when available.
cmd_tx
.send(ActorCommand::LocalAddr(tx))
.await
.map_err(|_| ActorHandleError::SendError)?;
crates/flow-service/src/flow_actor.rs:967
- As with the udp-notif actor, if the actor task fails immediately (e.g. socket bind failure), cmd_tx.send(LocalAddr) can race and fail with the receiver already dropped. Returning SendError here still hides the actor's real startup error; awaiting the join handle on send failure would better match the PR goal of surfacing early-exit failures.
cmd_tx
.send(FlowCollectorActorCommand::LocalAddr(tx))
.await
.map_err(|_| FlowCollectorActorHandleError::SendError)?;
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
fea2715 to
671861b
Compare
671861b to
b82c089
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Both handle error types now include non-Copy payloads but still match *self in Error::description(), which will not compile due to moving out of &self.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Lite
b82c089 to
39ad629
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new source() wiring still won’t expose underlying I/O errors (and still masks join/panic failures) unless the actor error types also implement source() and join failures are represented more precisely than ReceiveError/SendError.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 4
- Review effort level: Lite
FlowCollectorActorHandle::new collapsed any early actor exit (e.g. a socket bind failure) into a generic ReceiveError, discarding the real cause since the actor drops cmd_rx/the reply sender before the caller can read it. Race the initial command send and the reply recv against the actor's JoinHandle so early failures, panics, and clean early exits are each reported precisely. Also implement Error::source (replacing the deprecated Error::cause) on FlowCollectorActorError so the underlying I/O errors are chained.
Same issue as FlowCollectorActorHandle: ActorHandle::new collapsed any early actor exit (e.g. a socket bind failure) into a generic ReceiveError, discarding the real cause. Race the initial command send and the reply recv against the actor's JoinHandle so early failures, panics, and clean early exits are each reported precisely. Also implement Error::source on UdpNotifActorError so the underlying I/O errors are chained.
39ad629 to
32c60bc
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new startup failure modes and error variants aren’t covered by tests despite existing in-file test modules, increasing regression risk for this critical error-reporting behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Lite
Report the real cause when a collector actor fails to start, instead of
collapsing it into a generic "receiving response from actor" error.
Reason
FlowCollectorActorHandle::newandActorHandle::newsend an initialLocalAddrcommand to the freshly spawned actor task and await itsreply to learn the bound local address. If the actor fails early (e.g.
a UDP socket bind error) it exits and drops the command receiver /
reply sender, which previously surfaced to the caller only as a
generic
SendError/ReceiveError— the actual bind error (or panic)was silently discarded.
Changes
FlowCollectorActorError/UdpNotifActorErrornow implementError::source(replacing the deprecatedError::cause), chainingthe underlying I/O errors.
FlowCollectorActorHandleError/ActorHandleErrorgainActorFailed(_),ActorPanicked(_), andActorExitedvariantscarrying the real cause, in place of the old generic
ReceiveError.FlowCollectorActorHandle::new/ActorHandle::newrace the initialcommand send and reply recv against the actor's
JoinHandle(tokio::select! { biased; ... }) so an early actor failure,panic, or clean early exit is detected and reported precisely instead
of appearing as a channel error.