I am writing a ejabberd module where the user controls when the message is delivered to the recipient instead of delivering immediately(like birthday wishes sending in advance). This is done by adding a custom xml element to the message stanza like the following
<message xmlns="jabber:client" from="test2@ubuntu" to="test1@ubuntu/32375806281445450055240436" type="chat">
<schedule xmlns="ank" year="2015" month="10" day="19" hour="22" minute="36" second="13"/>
<body>hi</body>
</message>
Now these scheduled messages has to be stored in the mnesia database and send to the recipient when the time arrives.
Approach 1: One approach is to create a table for every user, when the message is received, store the message to the users table and set a timer to process the message and delete when done like the following sample code
timer:apply_after(SecondsDelay, ?MODULE, post_message_delete, [TableName, RecordUniqueKeyHash, From, To, Packet]).
The post_message_delete method will send the message when called after the timer expires using the route method as shown in the following and delete the record from the mnesia database.
ejabberd_router:route(From, To, Packet)
Creating a table for every user is not feasible due to the limitations on the number of tables in mnesia.
Approach 2: Another approach is to store all the users messages in one single table and set the timer(same as above) for every message as the message arrives and once the message is processed delete it.
The whole idea of using the mnesia database is to process the messages reliably in the case of ejabberd server crash.
To achieve this we use a pid field in the record of every message. There is a pid field for every message record that contains the pid of the process that is processing this message. Initially it is undefined(When the message arrives at the filter_packet hook) but after when the message processing method is spawned it updates the pid in the record in the mnesia database.
So if the server crashes on reboot in the modules start method all the messages are iterated and checked if the pid is alive(is_process_alive), if not alive then spawn the processing method on the message which will update with the new process pid, process the message and delte once done.
Drawbacks The drawback of this method is that even if a message has to be delivered far in the future(next month or next year) still a process is running for this message and there are as many processes running as there as many messages.
Approach 3:
To over come the drawbacks of Approach 2, scan the database every hour and accumulate the messages that has to be delivered only for the next hour and process it.
The drawback with this approach is that the database is scanned every hour that might impact performance.
Approach 4:
To over come the performance of Approach 3, we can create tables for every year_month and spawn the message processing function only on the current months table.
What other approach is best suited for this use case using mnesia database?