Open edkelly303 opened 3 years ago
It looks like the Erlang function can return an error, but it doesn't document why this might happen. I would be interested in knowing more about that
Oh, sorry, I missed that! (I am probably out of my depth here.)
Looking at the Erlang source, it seems that send_interval calls apply_interval, which returns an {error, badarg} if its To argument isn't really a Pid or a registered name.
I guess this isn't a concern for us because we know our Sender argument must contain a valid Pid?
Well spotted! Yes I think we can safely ignore that then.
I did some more research on this, and the plot thickens!
There are (at least) two different ways of doing delayed sends in Erlang using functions from the standard library, and they are built on two completely different implementations.
The Gleam's process.send_after
uses erlang:send_after
, which is implemented using a BIF/NIF. However, there's no similar BIF/NIF implementation of a send_interval
function in the erlang
module.
The Erlang implementation of send_interval
is actually in the timer
module, which has both timer:send_after
and timer:send_interval
. All the functions in timer
are implemented using ordinary Erlang processes & ETS tables, not special BIFs/NIFs.
The timer
processes can get overloaded and are less efficient than erlang:send_after
, so there's a warning about using them for any application that sets/cancels lots of timers: http://erlang.org/doc/efficiency_guide/commoncaveats.html#id65681.
We could use a combination of erlang:send_after
(for efficiency) and timer:send_interval
(for convenience), but because the underlying implementations are completely different, the TimerRef
returned by erlang:send_after
is not compatible with the TRef
returned by the functions in the timer
module. This is mostly a problem if we cant to cancel timers. To cancel a timer set by the timer
module, we need to use timer:cancel
, whereas to cancel a timer set by erlang:send_after
, we must use erlang:cancel_timer
.
Other options I can think of:
erlang:send_after
, and use it to implement a send_interval
function on the Gleam side. I'm not sure how to do this.gleam_timer
package that simply wraps the Erlang timer
module, so users can just add it as a dependency if they want send_interval
and aren't worried about the scalability issues.send_interval
function at all for now; it's easy enough for Gleam users to wire up their processes to send repeated messages to themselves using the existing process.send_after
function.Great research, very thorough. I like your suggestions a lot. I think I'd like to go with 3 and leave the community to implement 2.
If it turns out there is an excellent community solution we could later promote it into a core package if that's desired, but a community package could be the best solution long term.
As discussed on Discord with @lpil :
I'm guessing an implementation could look something like this: