Search code examples
erlangelixirerlang-otp

Elixir get all scheduled messages


I am using the following Process.send_after in order to schedule some event, my question is for given pid can i get all the scheduled events?


Solution

  • You are not scheduling an event, you schedule the message.

    Process.send_after/4 returns a reference to a timer. Since then neither the sender nor the receiver has anything in common with this scheduled message until it gets delivered to the receiver (or canceled by ErlangVM if the receiver died.) It’s handled by ErlangVM until the timer is expired. It will e. g. be canceled if the receiver specified by PID has gone.

    That said, without any manual record, it is impossible. What is possible, is to check the mailbox of the process having it’s PID. That said if the timer has already expired and the receiver did not consume the message yet, it might be queried:

    Process.send_after(self(), :hi, 10)
    #⇒ #Reference<0.3363662940.2222456833.225763>
    :erlang.process_info(self(), :message_queue_len)
    #⇒ {:message_queue_len, 1}
    :erlang.process_info(self(), :messages)
    #⇒ {:messages, [:hi]}
    

    You might relatively easy get the number of messages not yet consumed; you should collect timer references returned by Process.send_after/4 so that later you might query then:

    timers = 
      [
        Process.send_after(self(), :hi, 1_000_000),
        Process.send_after(self(), :hi, 1_000),
        Process.send_after(self(), :hi, 1_000_000)
      ]
    #⇒ [#Reference<0.3363662940.2222456833.225820>, ...]
    
    timers
    |> Enum.map(&Process.read_timer/1)
    |> Enum.count(& &1)
    #⇒ 2
    

    If you want to duplicate the functionality of ErlangVM, you might store your messages in ETS/DETS/whereever; there is no reliable (read: not hacky) way to retrieve this information from the VM.