Skip to content

Commit 7f20dc3

Browse files
authored
Better handling extended protocol messages in the event of busy pool (#155)
* Better handling for checkout errors during extended protocol messages * Fix specs * comment
1 parent 36339bd commit 7f20dc3

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

src/client.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -600,19 +600,32 @@ where
600600
message_result = read_message(&mut self.read) => message_result?
601601
};
602602

603-
// Avoid taking a server if the client just wants to disconnect.
604-
if message[0] as char == 'X' {
605-
debug!("Client disconnecting");
606-
return Ok(());
607-
}
608-
609603
// Handle admin database queries.
610604
if self.admin {
611605
debug!("Handling admin command");
612606
handle_admin(&mut self.write, message, self.client_server_map.clone()).await?;
613607
continue;
614608
}
615609

610+
match message[0] as char {
611+
// Buffer extended protocol messages even if we do not have
612+
// a server connection yet. Hopefully, when we get the S message
613+
// we'll be able to allocate a connection. Also, clients do not expect
614+
// the server to respond to these messages so even if we were not able to
615+
// allocate a connection, we wouldn't be able to send back an error message
616+
// to the client so we buffer them and defer the decision to error out or not
617+
// to when we get the S message
618+
'P' | 'B' | 'D' | 'E' => {
619+
self.buffer.put(&message[..]);
620+
continue;
621+
}
622+
'X' => {
623+
debug!("Client disconnecting");
624+
return Ok(());
625+
}
626+
_ => (),
627+
}
628+
616629
// Get a pool instance referenced by the most up-to-date
617630
// pointer. This ensures we always read the latest config
618631
// when starting a query.
@@ -714,22 +727,17 @@ where
714727
conn
715728
}
716729
Err(err) => {
717-
// Clients do not expect to get SystemError followed by ReadyForQuery in the middle
718-
// of extended protocol submission. So we will hold off on sending the actual error
719-
// message to the client until we get 'S' message
720-
match message[0] as char {
721-
'P' | 'B' | 'E' | 'D' => (),
722-
_ => {
723-
error_response(
724-
&mut self.write,
725-
"could not get connection from the pool",
726-
)
727-
.await?;
728-
}
729-
};
730-
730+
// Client is attempting to get results from the server,
731+
// but we were unable to grab a connection from the pool
732+
// We'll send back an error message and clean the extended
733+
// protocol buffer
734+
if message[0] as char == 'S' {
735+
error!("Got Sync message but failed to get a connection from the pool");
736+
self.buffer.clear();
737+
}
738+
error_response(&mut self.write, "could not get connection from the pool")
739+
.await?;
731740
error!("Could not get connection from pool: {:?}", err);
732-
733741
continue;
734742
}
735743
};

0 commit comments

Comments
 (0)