# Add a standard "ping" for processes?

**URL:** <https://erlangforums.com/t/add-a-standard-ping-for-processes/5071>\
**Category:** Proposals: Ideas\
**Tags:** processes\
**Created:** [September 17, 2025, 2:49pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071 "2025-09-17T14:49:13Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nathanl](https://erlangforums.com/user_avatar/erlangforums.com/nathanl/32/1842_2.png) [@nathanl](https://erlangforums.com/u/nathanl)\
**Post date:** [September 17, 2025, 2:49pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/1 "2025-09-17T14:49:13Z")

</div>

Question from Elixir land. I have a GenServer that receives a cast message and performs a side effect (a database update). In a test, I want to send the cast, wait “long enough”, then confirm that the side effect happened.

Some options for waiting “long enough”:

1. `Process.sleep/1` - bad because if it’s too short, the test will not consistently pass, but if it’s too long, the test will be slow. Also, the tests run slower in CI, which makes picking the right value tricky. A variant of this would be repeated, short “sleep and check” cycles, up to a timeout.
2. Modify the GenServer for the sake of the test to notify when it’s finished (eg via telemetry)
3. Modify the GenServer for the sake of the test to have a `handle_call(:ping`; when it replies, I’d know the prior message in the mailbox had been processed too
4. Use a standard, mailbox-dependent call like `:sys.get_state/1` or `:sys.get_status/1` - same idea as item 3 but no modification of the GenServer is needed. Minor downsides: it’s a bit wasteful since I don’t actually need the return value, and it requires code comments to explain why I’m calling it and ignoring the return value.
5. Modify the side effect function for the sake of the test to notify that it’s complete

I don’t love modifying code to emit events or handle messages solely for the sake of testing. Option 4 is my current choice, but it would be nice if there were a `:sys.ping(pid)` that would do the same thing - similar to what we have in `Node.ping/1` (although I know that has the side effect of establishing clustering if it’s not already established).

I thought that something like `:sys.ping(pid)` would probably already exist in Erlang, but if it does, I haven’t found it. Does it exist? If not, should it?

---

<div class="post-metadata">

**Author:** ![LeonardB](https://erlangforums.com/user_avatar/erlangforums.com/leonardb/32/1856_2.png) [@LeonardB](https://erlangforums.com/u/LeonardB)\
**Post date:** [September 17, 2025, 3:15pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/2 "2025-09-17T15:15:09Z")

</div>

you could maybe just change to do something along the lines of

```erlang
do_stuff({reply, Payload}) ->
    gen_server:call(?SERVER, {do_stuff, Payload});
do_stuff(Payload) ->
    gen_server:cast(?SERVER, {do_stuff, Payload}).

handle_call({do_stuff, Payload}, _From, State) ->
    MyReply = doing_stuff(Payload),
    {reply, MyReply, State}.

handle_cast({do_stuff, Payload}, State) ->
    _ = doing_stuff(Payload),
    {noreply, State}.

```

So in your test, just use `mod:do_stuff({reply, Payload})`

---

<div class="post-metadata">

**Author:** ![NAR](https://erlangforums.com/user_avatar/erlangforums.com/nar/32/1363_2.png) [@NAR](https://erlangforums.com/u/NAR)\
**Post date:** [September 17, 2025, 4:03pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/3 "2025-09-17T16:03:19Z")

</div>

I’d use the variant of the first version: “sleep and check the side effect” in a cycle. If the environment is fast, only a few checks are necessary and the test finishes fast. If the environment is slow, more checks are done, but it’s still robust.

---

<div class="post-metadata">

**Author:** ![mikpe](https://erlangforums.com/letter_avatar_proxy/v4/letter/m/b487fb/32.png) [@mikpe](https://erlangforums.com/u/mikpe)\
**Post date:** [September 17, 2025, 7:02pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/4 "2025-09-17T19:02:30Z")

</div>

Why not use (the equivalent of) gen\_server:call/3 instead? Using polling in this case feels like a kludge.

I.e., I’d go with option 5. Perhaps pass in an optional From in the cast, and when done with the side-effect do a gen\_server:reply (or equivalent) if the From is present.

---

<div class="post-metadata">

**Author:** ![elbrujohalcon](https://erlangforums.com/user_avatar/erlangforums.com/elbrujohalcon/32/241_2.png) [@elbrujohalcon](https://erlangforums.com/u/elbrujohalcon)\
**Post date:** [September 18, 2025, 5:55am UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/5 "2025-09-18T05:55:17Z")

</div>

I usually use option 4 and, to avoid comments explaining why… I wrap it up in a properly named function, like…

```erlang
wait_for_side_effects(OTPProcess) ->
    _ = sys:get_state(OTPProcess),
    done.

```

---

<div class="post-metadata">

**Author:** ![sverker](https://erlangforums.com/user_avatar/erlangforums.com/sverker/32/841_2.png) [@sverker](https://erlangforums.com/u/sverker)\
**Post date:** [September 18, 2025, 1:04pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/6 "2025-09-18T13:04:02Z")

</div>

Another option can be to use [Erlang tracing](https://www.erlang.org/docs/28/apps/kernel/trace.html) to know when otherwise unobservable events have happened.

---

<div class="post-metadata">

**Author:** ![elbrujohalcon](https://erlangforums.com/user_avatar/erlangforums.com/elbrujohalcon/32/241_2.png) [@elbrujohalcon](https://erlangforums.com/u/elbrujohalcon)\
**Post date:** [September 18, 2025, 1:29pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/7 "2025-09-18T13:29:21Z")

</div>

Yeah… [et for the win!](https://www.erlang.org/doc/apps/et/et#phone_home/4)

 ![image](https://erlangforums.com/uploads/default/original/2X/7/7216cbc7d6a2e7c188385711ce1819b664570f67.png)

---

<div class="post-metadata">

**Author:** ![rlipscombe](https://erlangforums.com/user_avatar/erlangforums.com/rlipscombe/32/459_2.png) [@rlipscombe](https://erlangforums.com/u/rlipscombe)\
**Post date:** [September 19, 2025, 8:17am UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/8 "2025-09-19T08:17:33Z")

</div>

> [@nathanl](#):
>
> then confirm that the side effect happened.

I’ve been using `telemetry` for this. You probably want some metrics anyway, right? So why not take advantage of that in your tests…?

See, for example, [kafine/test/kafine\_node\_consumer\_pause\_tests.erl at 0.28.0 · happening-oss/kafine · GitHub](https://github.com/happening-oss/kafine/blob/0.28.0/test/kafine_node_consumer_pause_tests.erl#L46-L50), in which we start a “node consumer” and then wait until it becomes idle before continuing with the rest of the test.

```erlang
    TelemetryRef = telemetry_test:attach_event_handlers(self(), [
        [kafine, node_consumer, idle],
        [kafine, node_consumer, continue]
    ]),

    {ok, Pid} = start_node_consumer(?CONSUMER_REF, Broker, TopicPartitionStates),

    receive
        {[kafine, node_consumer, idle], TelemetryRef, _, _} -> ok
    end,

    ?assertMatch({idle, _}, sys:get_state(Pid)),

```

The other nice thing about this is that you can use the telemetry event’s `Measurements` and `Metadata` to “smuggle” useful information back to the test.

---

<div class="post-metadata">

**Author:** ![ieQu1](https://erlangforums.com/user_avatar/erlangforums.com/iequ1/32/2633_2.png) [@ieQu1](https://erlangforums.com/u/ieQu1)\
**Post date:** [September 19, 2025, 8:09pm UTC](https://erlangforums.com/t/add-a-standard-ping-for-processes/5071/9 "2025-09-19T20:09:01Z")

</div>

We use [GitHub - kafka4beam/snabbkaffe: Distributed trace-based test framework with fault injection](https://github.com/kafka4beam/snabbkaffe) library for this purpose. Though it doesn’t satisfy the requirement

> I don’t love modifying code to emit events or handle messages solely for the sake of testing.

…But it is a powerful testing technique otherwise. For example, it allows to correlate effects from different nodes. If you print debug logs after completion of event processing, then you may as well replace them with the snabbkaffe tracepoints and use `?block_until` macro to synchronize testcase with the SUT.
