Partisan Cheatsheet

View Source

Configuring Partisan

Partisan is configured using the normal sys.conf file and/or calling the functions in the partisan_config module.

Example sys.config file

[
    {partisan, [
        %% Which overlay to use
        {peer_service_manager, partisan_pluggable_peer_service_manager},
        %% The listening port for Partisan TCP/IP connections
        {peer_port, 10200},
        %% The list of channels
        {channels, [{data, #{parallelism => 1}}]},
        %% Encoding for pid(), reference() and names
        {pid_encoding, false},
        {ref_encoding, false},
        {remote_ref_format, improper_list}
    ]},
    %% ...Other apps...
].

Notice that in order to work, all nodes in the cluster need to use the same configuration (apart from parameters like peer_port which can vary between nodes when deployed on the same host).

Connecting to other peers and sending messages

The following sections assumes you have two nodes running: ruby (ruby@127.0.0.1) and max (max@127.0.0.1).


Manually joining using Erlang's console

1. Obtain max's node specification

(max@127.0.0.1)1> NodeSpec = partisan:node_spec().

2. Join ruby with max

(ruby@127.0.0.1)1> NodeSpec = ...
(ruby@127.0.0.1)2> partisan_peer_service:join(NodeSpec).

NodeSpec is the value obtained at max in the previous step.

Checking cluster membership view

(max@127.0.0.1)1> partisan:nodes().

Returns [node()] and should contain both nodes.

Obtain max's shell pid

(max@127.0.0.1)2> partisan:self().
['max@127.0.0.1'|<<"#Pid<0.813.0>">>]

Returns partisan_remote_ref:t(). Notice this can be a tuple and improper list or a URI binary depending on the configuration option remote_ref_format which defaults to improper_list.

Send message from ruby to max

(ruby@127.0.0.1)3> Ref = ['max@127.0.0.1'|<<"#Pid<0.813.0>">>].
(ruby@127.0.0.1)4> partisan:forward_message(Ref, hello).

Check the message arrived at max

(max@127.0.0.1)3> flush().
Shell got hello
ok

Leave the cluster

(max@127.0.0.1)4> partisan_peer_service:leave().
ok

Migrating from Distributed Erlang

In addition to using Partisan-specific functions to manage a cluster and send messages, adopting Partisan implies the need to replace some Erlang BIFs with Partisan's counterparts. This is mainly to cope with the impossibility for Partisan to represent remote pids and references in the way Distributed Erlang does. Instead, a remote pid or reference is represented as a partisan_remote_ref:t/0.

By default (pid_encoding and ref_encoding both default to true), this encoding is automatic: any pid() or reference() found anywhere inside a message payload is transparently rewritten to a partisan_remote_ref:t() when the message is sent. You only need to call partisan_remote_ref:from_term/1 yourself when you disable automatic encoding, or when you want a reference to your own process or a value ahead of sending it (as partisan:self/0 does).

Several Erlang BIFs (a.k.a "native implementation") won't work when using Partisan so you will need to use the Partisan API instead. The Partisan API tries to be a drop-in replacement to Erlang's as much as possible. It tries comply with Erlang's in terms of naming, function signature and behaviour, so in most cases migrating to Partisan is as easy as replacing the module name from erlang to partisan.

The same applies for OTP behaviours when making remote calls e.g. gen_server:call/2 will not work when the first argument is a remote name. If you need your OTP behaviours to communicate over the network you will need to either (i) implement the partisan counterpart fork, i.e. partisan_gen_server; or (ii) use partisan_rpc:call/4 for an rpc-style remote call.

Notice also that calling sys functions e.g. sys:get_state/1 passing a remote partisan_gen_server reference will not work. You will also have to use the partisan counterpart partisan_sys:get_state/1.

The following table shows a mapping of Erlang to Partisan APIs.

ErlangPartisanDescription
erlang:cancel_timer/1partisan:cancel_timer/1Also cancels a timer created by partisan:send_after/3,4 for a remote destination.
erlang:cancel_timer/2partisan:cancel_timer/2Also cancels a timer created by partisan:send_after/3,4 for a remote destination.
erlang:demonitor/1partisan:demonitor/1Also accepts a partisan:remote_reference/0 returned by partisan:monitor/1,2,3. Unlike the native function, does not fail if the monitor was started by another process.
erlang:demonitor/2partisan:demonitor/2Also accepts a partisan:remote_reference/0 returned by partisan:monitor/1,2,3.
erlang:disconnect_node/1partisan:disconnect_node/1
erlang:exit/2partisan:exit/2Also accepts a partisan:remote_pid/0.
erlang:is_alive/0partisan:is_alive/0Different meaning: whether the peer service manager is running, not whether the node is registered for Distributed Erlang.
erlang:is_pid/1partisan:is_pid/1Also accepts a partisan:remote_pid/0.
erlang:is_process_alive/1partisan:is_process_alive/1Also accepts a partisan:remote_pid/0; the check runs on the owning node.
erlang:is_reference/1partisan:is_reference/1Also accepts a partisan:remote_reference/0.
erlang:make_ref/0partisan:make_ref/0Returns a partisan:remote_reference/0, not a native reference().
erlang:monitor/1partisan:monitor/1Deprecated; use partisan:monitor/2.
erlang:monitor/2partisan:monitor/2Also accepts a partisan:remote_pid/0 or partisan:remote_name/0, returning a partisan:remote_reference/0.
erlang:monitor/3partisan:monitor/3Also accepts a partisan:remote_pid/0 or partisan:remote_name/0, returning a partisan:remote_reference/0.
erlang:node/0partisan:node/0
erlang:node/1partisan:node/1Also accepts a partisan:remote_pid/0 or partisan:remote_reference/0, reading the node from the encoded reference.
erlang:process_info/1partisan:process_info/1Also accepts a partisan:remote_pid/0.
erlang:process_info/2partisan:process_info/2Also accepts a partisan:remote_pid/0.
erlang:self/0partisan:self/0Returns a partisan:remote_pid/0, not a native pid(). More expensive than erlang:self/0 — see partisan:self/1 to cache the result.
erlang:send/2partisan:send/2
erlang:send/3partisan:send/3
erlang:send_after/3partisan:send_after/3Accepts a partisan_remote_ref:t() as destination. When destination is a local pid, it reverts to the native implementation.
erlang:send_after/4partisan:send_after/4Accepts a partisan_remote_ref:t() as destination. When destination is a local pid, it reverts to the native implementation.
erlang:spawn/2partisan:spawn/2Returns a partisan:remote_pid/0. A remote spawn is carried out over partisan_rpc.
erlang:spawn/4partisan:spawn/4Returns a partisan:remote_pid/0. A remote spawn is carried out over partisan_rpc.
erlang:spawn_monitor/2partisan:spawn_monitor/2Returns a partisan:remote_pid/0 and partisan:remote_reference/0 pair for a remote target.
erlang:spawn_monitor/4partisan:spawn_monitor/4Returns a partisan:remote_pid/0 and partisan:remote_reference/0 pair for a remote target.
erlang:whereis/1partisan:whereis/1Also accepts a partisan:remote_name/0 for the local node; fails with badarg for a remote node.
net_kernel:monitor_node/2partisan:monitor_node/2
net_kernel:monitor_nodes/1partisan:monitor_nodes/1
net_kernel:monitor_nodes/2partisan:monitor_nodes/2