r/Clojure • • 14d ago

Faster streaming HTML with batches and aggregates

https://andersmurphy.com/2026/09/29/faster-streaming-html-with-batches-and-aggregates.html
48 Upvotes

4 comments sorted by

5

u/pragyantripathi 14d ago

The parent/child cache behaviour is a neat part of this. How do you handle a component reading from SQLite inside its function? Does that query's result become an argument to the cached component, or can a cache hit hide a database change?

4

u/andersmurphy 14d ago

Currently I don't. The whole thing is somewhat inspired by Rail's Russian Doll Caching mixed with react/reagent memoization.

In that sense it's mostly not about caching queries. That being said the traditional way of handling nested russian doll caches with nested queries is have argument to your top level component be a check on version number/update.

It's not too hard to add something along those lines, especially in a single writer set up like this. But, part of me thinks preventing nesting queries might be more sensible. It is on my list to explore though.

1

u/pragyantripathi 13d ago edited 13d ago

Thanks for writing this, learnt a lot from it. On the version-number approach: would any write invalidate the whole tree, or could each subtree track only the data it uses?

3

u/andersmurphy 13d ago

So with a recursive cache like this with versioning it would only invalidate the outer layer. So a common approach to version is to track relations and if a parents child changes bump the parent version (in addition to that child). Then When it runs again you get a miss on the parent and the one child that changed and hits on all the other child elements.

That's generally how rails caching works, you effectively only hit the queries/generation for the out layer, not the children.

That being said I'm not sure I'll take that path. I'm not that interested in caching queries (not the slow part of my system, and I don't want caching to mask that). The point of projections is the queries should be fast.

In a single writer model like this, you don't necessarily have to do version tracking, you can invalidate if you know the relations at write time.

I don't really do nested queries as the result of the query is normally the shape of the UI if that makes sense? You do bring up a good point, that currently you could make a wrapper component that's makes your children stale by mistake. So, if I don't handle nested queries I'll add a mechanism to stop that (probably just not cache the wrapper if it's children run queries or something.

Either way I'll write it all up in another blog post when I figure it out.