Clojure atoms are great. It allows us to separate between the state and the value of the state at some point in time.
I could see atoms used in applications that manage state internally, like a frontend application. But in the backend, it seems to me that most modern web services are either stateless or manage their states externally (e.g. in a database).
So here is my question: what are the most common use cases for Clojure atoms in modern web services?
I use a modified atom to store session-id → saml-assertions. Those SAML sessions are supposed to expire within 8 hours, so persisting them in a database would make it much less convenient and more error-prone to do so.
This essentially replaces Shibboleth (which my predecessor used everywhere) and Shibboleth – at least in our setups – does use the database to store SAML assertions. I’ve probably had to manually fix out-of-sync rows in the database about 8-10 times last year which prevented people from logging in.
…
I also use an atom to store the current system configuration that was loaded from disk and an atom to store the Pedestal web server instance.
Does it mean that when your app restarts, people are logged out?
Statelessness in the backend is, for me, an important concept. Because scaling to multiple replica’s of my app later on would be a bit painful if i depended too much on atoms.
That said, I use it for a few small things, like keepign track of the state of a long running job, and then there’s an http endpoint that the frontend can poll to get that state.
Bit quick/dirty and not resistent to jar restarts, and not scalable when there’s multiple apps involved, but a nice pragmatic approach for when it’s fine to do so
It is is a tool for a small selection of researchers and it runs on a single server, I’m not making facebook And SAML logins are not really meant to be long-running anyway. In theory I could persist the contents of the atom to disk and reload that, but once it’s done, it’s done (the web service, that is), so it will rarely be updated anyway. I’ll move on to other research projects.
I think it also has the benefit of eliminating some GDPR requirements.
On top of what others have said, we have a search service that loads the index in-memory, we need to update the index without app restart or downtime, and atoms are great for doing a runtime atomic swap.
I use Integrant for all my state management, but I find it useful to have some of that (e.g., a reference to a Crux node, or a Cassandra connection) “mirrored” in an atom. I use this extensively when developing, and if I want to quickly check stuff via nREPL on a running instance. I had intended to remove the atoms after setting up Integrant, but I just found it handy to keep them around. They are never used from actual working code, though.