Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions crates/flow-service/src/flow_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,13 +892,18 @@ pub enum FlowCollectorActorHandleError {
SendError,
#[strum(to_string = "Error receiving response from actor")]
ReceiveError,
#[strum(to_string = "actor terminated before it could start: {0}")]
ActorFailed(FlowCollectorActorError),
}

impl std::error::Error for FlowCollectorActorHandleError {
fn description(&self) -> &str {
match *self {
FlowCollectorActorHandleError::SendError => "Error sending command to actor",
FlowCollectorActorHandleError::ReceiveError => "Error receiving response from actor",
FlowCollectorActorHandleError::ActorFailed(_) => {
"actor terminated before it could start"
}
}
Comment on lines 899 to 907
}

Expand Down Expand Up @@ -954,17 +959,35 @@ impl FlowCollectorActorHandle {
subscriber_timeout,
stats,
);
let join_handle = tokio::spawn(actor.run());
let mut join_handle = tokio::spawn(actor.run());
let (tx, mut rx) = mpsc::channel(cmd_buffer_size);
cmd_tx
.send(FlowCollectorActorCommand::LocalAddr(tx))
.await
.map_err(|_| FlowCollectorActorHandleError::SendError)?;
let local_addr = rx
.recv()
.await
.ok_or(FlowCollectorActorHandleError::ReceiveError)?
.1;
let local_addr = tokio::select! {
biased;
res = &mut join_handle => {
return Err(match res {
Ok(Err(err)) => FlowCollectorActorHandleError::ActorFailed(err),
_ => FlowCollectorActorHandleError::ReceiveError,
});
}
local = rx.recv() => {
match local {
Some((_, addr)) => addr,
// The reply sender was dropped without a response, most likely
// because the actor task exited early (e.g. socket bind
// failure). Await the join handle to surface the real cause.
None => {
return Err(match join_handle.await {
Ok(Err(err)) => FlowCollectorActorHandleError::ActorFailed(err),
_ => FlowCollectorActorHandleError::ReceiveError,
});
}
}
}
};
Ok((
join_handle,
Self {
Expand Down
29 changes: 27 additions & 2 deletions crates/udp-notif-service/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,13 +972,16 @@ pub enum ActorHandleError {
SendError,
#[strum(to_string = "error receiving response from actor")]
ReceiveError,
#[strum(to_string = "actor terminated before it could start: {0}")]
ActorFailed(UdpNotifActorError),
}

impl std::error::Error for ActorHandleError {
fn description(&self) -> &str {
match *self {
ActorHandleError::SendError => "error sending command to actor",
ActorHandleError::ReceiveError => "error receiving response from actor",
ActorHandleError::ActorFailed(_) => "actor terminated before it could start",
}
Comment on lines 981 to 985
}

Expand Down Expand Up @@ -1034,13 +1037,35 @@ impl ActorHandle {
reassembly_timeout,
stats,
);
let join_handle = tokio::spawn(actor.run());
let mut join_handle = tokio::spawn(actor.run());
let (tx, mut rx) = mpsc::channel(cmd_buffer_size);
cmd_tx
.send(ActorCommand::LocalAddr(tx))
.await
.map_err(|_| ActorHandleError::SendError)?;
let local_addr = rx.recv().await.ok_or(ActorHandleError::ReceiveError)?.1;
let local_addr = tokio::select! {
biased;
res = &mut join_handle => {
return Err(match res {
Ok(Err(err)) => ActorHandleError::ActorFailed(err),
_ => ActorHandleError::ReceiveError,
});
}
local = rx.recv() => {
match local {
Some((_, addr)) => addr,
// The reply sender was dropped without a response, most likely
// because the actor task exited early (e.g. socket bind
// failure). Await the join handle to surface the real cause.
None => {
return Err(match join_handle.await {
Ok(Err(err)) => ActorHandleError::ActorFailed(err),
_ => ActorHandleError::ReceiveError,
});
}
}
}
};
Ok((
join_handle,
Self {
Expand Down