rhoulam
technologies llc

chronos Initial Release (v0.1.0)

December 5, 2022

erlang, library, open source, chronos

A project in Erlang yielded this very general timeout-management server.

The project required scheduling future actions, and it was clear that each process creating timeouts for this was unwieldy. There was also the question of what to do in case of downtime. This inspired chronos.

Chronos maintains a state object containing scheduled tasks (registered actions), who scheduled them (as a name), and their reference IDs. The client processes retain the reference ID in order to distinguish which tasks have come due, in the case they schedule multiple.

Chronos state is stored into a file when shut down, and it will resume from the contents of the state file when started again with the same state file path. When restoring from the contents of a state file, chronos will fast-forward to the current time, notifying client processes that their tasks have come (over)due for all scheduled tasks until the present timestamp. For this reason, chronos should be started after all the processes that utilize it, in order that they will be up to receive overdue notifications.

Chronos’s core lifecycle is simple. It maintains one timeout for the item that will become due the soonest, and sets a timeout upon completion for the next one. Scheduling tasks (registering actions) may require that we cancel this timeout in the case that the new task is the soonest to come due. Also canceling tasks (deregistering actions), in the case that the soonest to become due is canceled, will require canceling the outstanding timeout.

Client processes are notified by a standard Erlang message of the form {chronos_timeout, ReferenceId} that their task has come due. In the gen_server pattern, this will be caught by handle_info. Clients are referenced by atom, so they must be registered and they must register the same name on restart in order for chronos’s state loading feature to function properly. Also the ReferenceId is not an Erlang reference, since that is not reliable across restarts; it is a binary generated by chronos:mk_opaque_token/0 consisting of a combination of the current timestamp and uniform random bits.

As a rule of thumb, if your application needs to reimplement a subset of cron, chronos is probably going to be an asset.

GitHub