How to model this runtime config in Ash?
What's the normal way to have a singleton resource that is saved in postgres, but has a read-only copy in ETS? I'm trying to think of how I might migrate one part of my app to Ash.
In my app I have a global runtime configuration struct. Basically this is a config that admin users should be able to modify at runtime via a json API (or maybe the Ash admin UI 🤔) and it's supposed to affect the behavior of the system at runtime. Right now this config has a table in postgres with a custom unique index
(true)
. This means that only one row is allowed in the table. The table itself just has one column which is a JSONB type. When the app starts up it reads this config and saves it with Application.put_env
. Then in various places in the app I just fetch the config from the application env and pattern match out what I need. I could probably use persistent_term, but it's not a big struct. When a change is made to this config struct I update the database row and use Oban.Notifier
to broadcast a message to all other instances of my app to tell them to refresh their application env cache of the config.
What would be the Ash way to implement this? It doesn't have to work exactly like this. This is the best I came up with, but I'm happy to hear alternatives 🙂3 Replies
P.S. The reason I use
Oban.Notifier
is cause it uses postgres notifications by default. One part of my app's functionality is that you can provide environment variables for credentials and after the app loads the config from the database, it checks if any of those environment variables are set and if they are, then it immediately updates the database and broadcasts a message. Because this happens right after launch, I think there is potential for a race condition. If I used Phoenix.Pubsub
combined with DNSCluster
there's probably a chance the newly-deployed instance of my app with environment variable overrides updates the database and broadcasts a message before it discovers its cluster members. But we have to connect to the database anyway to read the config, so using Postgres notifications feels safer.
P.P.S. Apologies if this is already clear from somewhere in the docs. I haven't skimmed them yet.
Based on my current limited understanding, I imagine I could replicate this by using postgres as the config resource's data layer, then I customize the update
action to call Oban.Notifier.notify(...)
after the update completes. Then in my GenServer that listens to these broadcasts I read the config from postgres and update my application env.
Am I on the right track? Is this good 🤔
This way basically everything would be the same as before. I just have to invoke Ash's read
, create
and update
functions instead of Ecto's.What you've described would work yes, but you can also look at using generic actions, which are essentially just simple typed functions
Can do pretty much anything you like regardless of how conventional etc
Guess that counts as solved 🤷