Skip to content

Commit ca2eb6a

Browse files
committed
avoid buffering the shell in memory on the server until the first component has rendered
See #435
1 parent ea020db commit ca2eb6a

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- Add a `wrap` attribute to the `list` component to wrap items on multiple lines when they are too long.
3535
- 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.
3636
- Update sqlite to v3.46: https://www.sqlite.org/releaselog/3_46_0.html
37+
- 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.
3738
3839
## 0.23.0 (2024-06-09)
3940

src/webserver/http.rs

+14
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ impl ResponseWriter {
7070
if self.buffer.is_empty() {
7171
return Ok(());
7272
}
73+
log::trace!(
74+
"Async flushing data to client: {}",
75+
String::from_utf8_lossy(&self.buffer)
76+
);
7377
self.response_bytes
7478
.send(Ok(mem::take(&mut self.buffer).into()))
7579
.await
@@ -91,6 +95,10 @@ impl Write for ResponseWriter {
9195
Ok(buf.len())
9296
}
9397
fn flush(&mut self) -> std::io::Result<()> {
98+
log::trace!(
99+
"Flushing data to client: {}",
100+
String::from_utf8_lossy(&self.buffer)
101+
);
94102
self.response_bytes
95103
.try_send(Ok(mem::take(&mut self.buffer).into()))
96104
.map_err(|e|
@@ -115,6 +123,12 @@ async fn stream_response(
115123
mut renderer: RenderContext<ResponseWriter>,
116124
) {
117125
let mut stream = Box::pin(stream);
126+
127+
if let Err(e) = &renderer.writer.async_flush().await {
128+
log::error!("Unable to flush initial data to client: {e}");
129+
return;
130+
}
131+
118132
while let Some(item) = stream.next().await {
119133
log::trace!("Received item from database: {item:?}");
120134
let render_result = match item {

0 commit comments

Comments
 (0)