Jan 15, 2023

Something I thought about earlier this week that I wanna better wrap my head around is the idea of reactive records, or reactive tables.

The basic idea is that instead of having general handler functions that manipulate a lot of tables all at once, you instead have messages that each table can opt-in to subscribing to. This would mean that update logic is spread out over more non-colocated pieces, but it also means that each update piece is easier to wrap your head around.

The catch I haven’t been able to figure out is changes that rely on other changes. For example, creating a profile record and then with the created ID, sending out a notification to everyone who had that persons phone number in their contact list. Right now that’s handled through Ecto.multi(), and it’s fairly intuitive and I have no desire to change it. I don’t like that each update step is complicated though.

The only idea I had was that record updates could publish their own messages that other tables could listen to as well, in addition to just client-sent messages. Thinking about this in Elm, you can only really do affects all at once before they are allowed to change the model. If you need to run an effect that changes the model, and then another effect that depends on that new model, you basically have to run them in a top-down loop, and tbf I guess that is desired. My question is: is that desirable for backend? My intuition is no, mainly because it creates eventual consistency and prevents you from making atomic updates, which are really desirable. A good example of this is creating a list of questions for a profile. When a profile is created, you want to immediately assign them some question records. Doing this as a series of reactive steps would be really difficult to manage.

Another idea is to just refactor changes on an individual table to be housed in that table. But I feel like that just creates a lot of arbitrary handlers in other modules. For example, profile records need to be updated when answering a question, but not when boosting a question. And moreover, the profile data that needs to be updated is just when the person last answered a question, which in theory is just a cached value. So having something like a Profile.update_last_answered_at() kinda feels like an arbitrary thing to remember to do, rather than a nice, generalized rule.