Skip to content

Commit

Permalink
avoid buffering the shell in memory on the server until the first com…
Browse files Browse the repository at this point in the history
…ponent has rendered

See #435
  • Loading branch information
lovasoa committed Jun 23, 2024
1 parent ea020db commit ca2eb6a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
- Add a `wrap` attribute to the `list` component to wrap items on multiple lines when they are too long.
- New `max_pending_rows` [configuration option](https://sql.ophir.dev/configuration.md) to limit the number of messages that can be sent to the client before they are read. Usefule when sending large amounts of data to slow clients.
- Update sqlite to v3.46: https://www.sqlite.org/releaselog/3_46_0.html
- Faster initial page load. SQLPage used to wait for the first component to be rendered before sending the shell to the client. We now send the shell immediately, and the first component as soon as it is ready. This can make the initial page load faster, especially when the first component requires a long computation on the database side.
## 0.23.0 (2024-06-09)
Expand Down
14 changes: 14 additions & 0 deletions src/webserver/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ impl ResponseWriter {
if self.buffer.is_empty() {
return Ok(());
}
log::trace!(
"Async flushing data to client: {}",
String::from_utf8_lossy(&self.buffer)
);
self.response_bytes
.send(Ok(mem::take(&mut self.buffer).into()))
.await
Expand All @@ -91,6 +95,10 @@ impl Write for ResponseWriter {
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
log::trace!(
"Flushing data to client: {}",
String::from_utf8_lossy(&self.buffer)
);
self.response_bytes
.try_send(Ok(mem::take(&mut self.buffer).into()))
.map_err(|e|
Expand All @@ -115,6 +123,12 @@ async fn stream_response(
mut renderer: RenderContext<ResponseWriter>,
) {
let mut stream = Box::pin(stream);

if let Err(e) = &renderer.writer.async_flush().await {
log::error!("Unable to flush initial data to client: {e}");
return;
}

while let Some(item) = stream.next().await {
log::trace!("Received item from database: {item:?}");
let render_result = match item {
Expand Down

0 comments on commit ca2eb6a

Please sign in to comment.