-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Database change notifications with Server-sent Events (SSE) #1807
base: master
Are you sure you want to change the base?
Conversation
Open to suggestions about the naming. Not quite sure Edit: Changed to |
At this point, should we consider integrating HTMX as part of IHP? |
Although (just to be clear) this implementation is purely frontend agnostic, I would most certainly use an HTMX boilerplate :) |
Converting it back to draft for now and letting it sit until I try it in real-life production first. I think the API could be improived |
Sounds good, let me know when things are for further review 👍 |
@mpscholten do you know if there already exists a good way to use row-level security (or something else) to prevent that the postgres notification triggers each time any column in the tracked tables changes? |
To make it work with RLS you need to refetch the data on every change. This is how it's done in DataSync as well. You can likely copy the code from here: https://github.com/digitallyinduced/ihp/blob/master/IHP/DataSync/ControllerImpl.hs#L138 It uses |
thanks 🙏 |
Ref #1800
Usage example: https://github.com/kodeFant/ihp-sse
This is a proposal for enabling EventSouce endpoints that subscribe to database changes through Server-sent Events (SSE), letting you execute custom behaviour on the client triggered by change notifications from the database.
What's the win here, really?
The simplicity of
autoRefresh
, but allows fine-grained control on what and how updates reflect in the view.No need to make stateful SPA component islands if you need to only auto-refresh certain parts of the page. Just have the database be the source of truth and sync the data, for example with htmx.
One example that is currently not easy with other techniques in IHP: An always in-sync inbox indicator in the navbar layout showing amount of unread messages.
With autoRefresh, you would need to use autoRefresh everywhere and explicitly track that table in every endpoint since it doesn't take in arguments from the controller, definitely not the right tool for this job.
With DataSync, it's a bit of overkill to set up just for this little feature.
Long-polling could be a viable option, but it means higher latency, more bandwidth-hungry and a higher toll on server resources.
Syncronizing this with SSE is simple, non-hacky, and cheap.
Why SSE
Browser support: https://caniuse.com/eventsource
Description
Like
autoRefresh
it tracks tables, but instead of forcing a full page reload, you create an EventSouce endpoint that will subscribe to PostgreSQL event triggers.Here is the controller code that is needed to make an event listener endpoint. You can track more than only one table if needed:
Note that even though this is an HTTP endpoint, it does not render html or JSON, but streams an
EventSouce
subscription to the client.Practically, this can give you
DataSync
with equal barrier to entry asautoRefresh
.Some advantages over DataSync is less need for JavaScript, and also very little Haskell code as seen above.
This for example hydrates updated HTML from
PostAction
into the view each time theposts_updated
event is triggered from theStreamPostsEvents
endpoint we defined above.Instead of HTMX, you could also recieve these events from JavaScript directly by instantiating an
EventSource
. In other words, this can be equally useful for those who use vanilla JS or jquery.The example below could be an example solution on how to solve an unread messages indicator as described above.
TODO
Look at possibility for making SSE endpoints that responds with HTML data directly(I think better to look at later)