@yawaramin, you’re completely right that sticking to something existing and battle-tested is always a safe and performant solution. For the use cases I listed, it’s clearly reasonable to use any of the solutions you listed.
@edwin Indeed, you’re completely right: the first line of defense here is proper asset versioning so that assets are served with a long cache lifetime, as we added in serve css/js assets under digest urls, cache-control by sabine · Pull Request #929 · ocaml/ocaml.org · GitHub. We didn’t go through the other assets yet, that’s an open issue which is very suitable for an OCaml newcomer to contribute to: Use `Ocamlorg_static.Asset.url` for all assets · Issue #1049 · ocaml/ocaml.org · GitHub. For the assets associated with the markdown content, it’s also a manageable issue that we would be very happy to guide and teach a contributor to work on.
(When I get annoyed enough at the issue, I will fix it myself, but chances are that there will be things that are much more urgent/impactful in the bigger scheme of things, so they get worked on.)
And some code here to respond with some very basic caching headers: […]
Once the code is fixed to serve headers for all static/immutable content correctly, that Dream middleware could potentially be generalized and released as its own package.
Indeed, if there is no dream middleware that already allows you to specify cache headers using a typed interface, this sounds like a good idea! (For example, when I fiddle with nginx, I tend to end up wasting so much time debugging typos or misplaced commas, it’s not funny - maybe other people do well at that, but I really like the guard-rails that types provide).
Django, Rails and its relatives do come as a batteries-included solution that enables people who don’t yet know about all these details to build websites by providing them with facilities that impose reasonable defaults and options. Their value lies in limiting the amount of available choices to the currently reasonable ones. That comes with some maintenance work, as what is reasonable sometimes changes over time as technology evolves. IMO Dream is doing a great job at this, and I am thinking… like Django and Rails, which have a flourishing ecosystem in their own, it would be cool to have that for Dream as well.
But I’m also coming from the perspective of time being quite limited, so whatever we do it should be sensible in regards of not reinventing the wheel from ground up but instead incrementally adding to the ecosystem in places where people would actually make use of it.
For example, when there are some production-ready bindings/clients to general-purpose key-value stores like memcached, Redis, my impression is that it would be reasonable to write a library that provides a generic cache-interface with pluggable backends (if a reasonable such library doesn’t exist already! If it does, we obviously use it). Checking on that, I see that a client for Redis exist: redis 0.7.1 (latest) · OCaml Package, searching for memcached, I see an abandoned-looking project built on the
This cache-interface library, in turn, could be integrated into a Dream middleware to cache HTTP responses. But the same cache-abstraction could as well be used to cache other data than just HTTP responses, e.g. in a session cache.
@rbjorklin Indeed, we are in a deployment situation where we, in principle, could add nginx or haproxy to our Docker container. However, I think… this might be a situation where it’s worth to at least check if the OCaml community’s ecosystem has us covered already, and, if not, consider adding to the ecosystem. IMO, adding bindings and clients to commonly-used technology would be, in general, useful.
Considering that tools like haproxy and nginx also have a learning curve attached, I’m not instantly taking the “easy for me” route of adding nginx. Instead, I’m genuinely curious if you think, in this case, adding to the ecosystem would be both useful and feasible.