Hello all,
so, I have done my research and the first successful experiments (mostly in IEx). I will develop a functional library but I'd like some inputs from you guys. First, here are my findings:
1) To use LISTEN/NOTIFY, you need to be sure there is a connection where the LISTEN commands have been issued. This is important, because LISTENs are per-connection. My approach here would be to have a dedicated process keeping this one single connection alive and restarting it as needed, reissuing the LISTEN commands on each reconnect. This would happens outside and independent from the connection pool used for querying.
2) NOTIFY, obviously, is issued by the database. This means triggers in the database would need to be created manually, possibly as part of a migration. NOTIFY has, other than the channel name, also a payload. Its content would be just forwarded. I think most of the times this would be an ID though.
My idea for this would be to have the following structure (more or less):
Supervisor (one_for_one)
* -- Agent storing channel/callbacks tuples
* -- Supervisor (all_for_one)
* -- Postgrex.Connection
* -- Process sending LISTEN commands and waiting for notifications and starting tasks to invoke callbacks
The process that sends LISTEN commands must also be the one waiting because Postgrex sends the notification to that process. This means adding/remove callbacks dynamically would require supporting some other messages as well in that process.
My doubts are about the API.
1) How should I store callbacks? Just funs or {module, function_name} couples? Or both?
2) Should the API be declarative (with macros you could invoke when defining a model for example) or dynamic (add_handler/remove_handler, etc). When all listeners and callbacks are defined at compile time, maybe I can even avoid having an Agent since I could store channel/callbacks as module attributes. In that case only the {module, function_name} form for callbacks would be possible I think. Correct me if I am wrong.
I tend for a declarative API, since I do not see it particularly useful to add/remove callbacks dynamically. Triggers in the database are usually not created dynamically either.
Another question is: I can publish this a project totally independent from Ecto. The only dependency would really be Postgrex (other DBMS could be supported as well, but MySQL, notably, would require polling since it does not have NOTIFY). José, do you think it makes sense to add this to Ecto instead (a sort of Ecto.Live or Ecto.Events module)?
Regards,
Michele