This is of course possible, here is a crude example in Erlang:
-module(dsup).
-export([
main/0
]).
-export([
child_init/1,
child_loop/1
]).
-behaviour(supervisor).
-export([
init/1
]).
% Demo entry point
main() ->
{ok, _, Node} = peer:start_link(),
supervisor:start_link({local, ?MODULE}, ?MODULE, [Node]).
% Child process init
child_init(Node) ->
Parent = self(),
{ok, proc_lib:spawn_link(Node, ?MODULE, child_loop, [Parent])}.
% Child process main loop
child_loop(Parent) ->
receive
{echo, From, Message} ->
From ! {echoed, Message},
child_loop(Parent);
{stop, From, Reason} ->
From ! ok,
exit(Reason)
end.
% Supervisor init callback
init([Node]) ->
Flags = #{},
Children = [
#{
id => child,
start => {?MODULE, child_init, [Node]}
}
],
{ok, {Flags, Children}}.
The only thing a supervisor care about is a that a child start function starts a new process, liinks it to the supervisor and return the {ok, Pid}
(or {ok, Pid, Info}
), the Pid can be started on a remote node as the example above show.
Here is an example session:
> erl -sname node1
Erlang/OTP 27 [erts-15.1.2] [source] [64-bit] [smp:14:14] [ds:14:14:10] [async-threads:1] [jit] [dtrace]
Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
(node1@Delta-23)1> c(dsup).
{ok,dsup}
(node1@Delta-23)2> dsup:test().
{ok,<0.101.0>}
(node1@Delta-23)3> supervisor:which_children(dsup).
[{child,<15315.91.0>,worker,[dsup]}]
(node1@Delta-23)4> ChildPid = pid(15315,91,0), ChildPid ! {echo, self(), "hello"}.
{echo,<0.90.0>,"hello"}
(node1@Delta-23)5> flush().
Shell got {echoed,"hello"}
ok
(node1@Delta-23)6> ChildPid ! {stop, self(), crashed}.
{stop,<0.90.0>,crashed}
=SUPERVISOR REPORT==== 19-Dec-2024::18:59:02.505399 ===
supervisor: {local,dsup}
errorContext: child_terminated
reason: crashed
offender: [{pid,<15315.91.0>},
{id,child},
{mfargs,{dsup,child_init,['peer-2242-11228@Delta-23']}},
{restart_type,permanent},
{significant,false},
{shutdown,5000},
{child_type,worker}]
=CRASH REPORT==== 19-Dec-2024::18:59:02.505058 ===
crasher:
initial call: dsup:child_loop/1
pid: <15315.91.0>
registered_name: []
exception exit: crashed
in function dsup:child_loop/1 (dsup.erl, line 36)
ancestors: [dsup,<0.90.0>,<0.89.0>,<0.76.0>,<0.71.0>,<0.75.0>,<0.70.0>,
kernel_sup,<0.47.0>]
message_queue_len: 2
messages: [{exit,crashed},{exit,<0.90.0>,crashed}]
links: [<0.101.0>]
dictionary: []
trap_exit: false
status: running
heap_size: 376
stack_size: 29
reductions: 168
neighbours:
(node1@Delta-23)7> supervisor:which_children(dsup).
[{child,<15315.92.0>,worker,[dsup]}]
As you can see in the last line, the supervisor restarted the process on the remote node.
That being said, you might probably want to take a look at the distributed applications guide for your use case (Distributed Applications — Erlang System Documentation v27.2)
Hope this helps.