(&mut self, payload_len: usize)
| 1484 | } |
| 1485 | |
| 1486 | fn recover_protocol_error(&mut self, payload_len: usize) -> Result<()> { |
| 1487 | self.protocol |
| 1488 | .recover_error |
| 1489 | .call(&mut self.store) |
| 1490 | .context("PostgresMainLongJmp after protocol trap")?; |
| 1491 | |
| 1492 | // PostgreSQL extended-query errors skip messages until Sync. If Sync was |
| 1493 | // already in this host buffer, re-enter the loop to drain it and produce |
| 1494 | // ReadyForQuery from PostgreSQL rather than inventing one in Rust. |
| 1495 | let max_drain_attempts = (payload_len / 5).saturating_add(2).max(1); |
| 1496 | let mut drain_attempts = 0usize; |
| 1497 | while self.protocol_input_remaining()? > 0 { |
| 1498 | drain_attempts += 1; |
| 1499 | ensure!( |
| 1500 | drain_attempts <= max_drain_attempts, |
| 1501 | "Postgres protocol recovery did not drain buffered input after {drain_attempts} attempts" |
| 1502 | ); |
| 1503 | if let Err(drain_err) = self.protocol.main_loop.call(&mut self.store) { |
| 1504 | if runtime_error_exit_code(&drain_err) == Some(POSTGRES_MAIN_LONGJMP) |
| 1505 | || is_wasm_uncaught_exception(&drain_err) |
| 1506 | { |
| 1507 | debug!( |
| 1508 | "PostgresMainLoopOnce trapped while draining after PostgreSQL error recovery: {drain_err}" |
| 1509 | ); |
| 1510 | } else { |
| 1511 | warn!( |
| 1512 | "PostgresMainLoopOnce trapped while draining after recovery: {drain_err}" |
| 1513 | ); |
| 1514 | } |
| 1515 | self.protocol |
| 1516 | .recover_error |
| 1517 | .call(&mut self.store) |
| 1518 | .context("PostgresMainLongJmp while draining after protocol trap")?; |
| 1519 | } |
| 1520 | } |
| 1521 | Ok(()) |
| 1522 | } |
| 1523 | |
| 1524 | fn recover_non_trapping_protocol_error(&mut self) -> Result<()> { |
| 1525 | self.protocol |
no test coverage detected