partisan_monitor (partisan v6.0.0)

View Source

This module is responsible for monitoring processes on remote nodes and implementing the monitoring API provided by the partisan module which follows the API provided by the Erlang modules erlang and net_kernel.

YOU SHOULD NEVER USE the functions in this module directly. Use the related functions in partisan instead.

NOTICE

At the moment this only works for partisan_pluggable_peer_service_manager backend.

Also, certain partisan_peer_service_manager implementations might not support the partisan_peer_service_manager:on_up/2 and partisan_peer_service_manager:on_down/2 callbacks which we need for node monitoring, so in those cases this module will not work.

Summary

Functions

Remove a monitor previously installed by monitor/2. Returns true if the monitor was active and false if it had already fired or was already removed (matching erlang:demonitor/2).

Monitor a remote process. Returns a partisan monitor reference that can be passed to demonitor/2.

Monitor the status of the node Node. If Flag is true, monitoring is turned on. If Flag is false, monitoring is turned off.

Subscribe (or unsubscribe) the calling process to node status change messages. While subscribed, a {nodeup, Node} message is delivered when a new node is connected and a {nodedown, Node} message is delivered when a node is disconnected. If nodedown_reason is in Opts the extended forms {nodeup, Node, InfoList} / {nodedown, Node, InfoList} are delivered instead.

Starts the partisan_monitor server.

Types

node_mon/0

-type node_mon() :: {node(), pid()}.

node_type_mon/0

-type node_type_mon() ::
          #partisan_node_type_mon{key :: {Monitor :: pid(), Hash :: integer()},
                                  node_type :: all | visible | hidden,
                                  nodedown_reason :: boolean()}.

node_type_mon_opts/0

-type node_type_mon_opts() :: {Type :: all | visible | hidden, InclReason :: boolean()}.

proc_mon_in/0

-type proc_mon_in() ::
          #partisan_proc_mon_in{ref :: reference(),
                                monitored :: pid() | atom(),
                                monitor :: partisan:remote_pid() | partisan:remote_name(),
                                channel :: partisan:channel()}.

proc_mon_in_idx/0

-type proc_mon_in_idx() :: {{node(), partisan:channel()}, reference()}.

proc_mon_out_idx/0

-type proc_mon_out_idx() :: {{node(), partisan:channel()}, partisan:remote_reference()}.

Functions

code_change(OldVsn, State, Extra)

demonitor(MonitoredRef, Opts)

-spec demonitor(MonitoredRef :: partisan:remote_reference(), Opts :: [partisan:demonitor_opt()]) ->
                   boolean() | no_return().

Remove a monitor previously installed by monitor/2. Returns true if the monitor was active and false if it had already fired or was already removed (matching erlang:demonitor/2).

Cleanup happens in two steps: the local bookkeeping (proc_mon_out) is removed synchronously, then a demonitor RPC is sent to the remote partisan_monitor server on the monitored node so it can drop its native monitor and forget the request. If that remote call fails because the peer is unreachable (noconnection, timeout, noproc, nodedown) the function returns true — we assume the remote side has already cleaned up and any in-flight DOWN will be either discarded by the transport or matched against a no-longer-active reference.

Options

flush
If a DOWN for this reference is currently in the calling process's mailbox, remove it. The flush is a best-effort local receive ... after 0 — partisan does not provide disterl's exact same-connection barrier, so a DOWN that has not yet been appended to the mailbox cannot be flushed. Pair with {channel, _} on the original monitor/2 call to keep the DOWN on the same connection as user traffic and minimise the window where flush can miss.

Failure

notalive
The partisan_monitor server is not running.
not_implemented
The active partisan peer service manager does not support the capabilities required for monitoring.
badarg
MonitoredRef is not a partisan remote reference, or Opts contains a malformed option.

handle_call(Msg, From, State)

handle_cast(Msg, State)

handle_info(Msg, State)

init(_)

monitor(Process, Opts)

Monitor a remote process. Returns a partisan monitor reference that can be passed to demonitor/2.

Unlike erlang:monitor/2, delivery of the DOWN signal is best-effort: the signal can be lost on transport disconnection, message loss, or peer-service tree reconfiguration. In those cases the monitor server will fabricate a DOWN with reason noconnection as soon as the disconnection is detected.

Channel binding

A monitor is bound to a single channel for its whole lifetime — by default the partisan default channel, or the channel passed in {channel, Channel}. The channel binding has two effects:

  1. The eventual DOWN signal travels over the same partisan connection as user traffic on Channel, so it is FIFO-ordered with any messages the monitored process sent on that channel before terminating — matching the disterl guarantee that messages from a dying process are delivered before its DOWN.
  2. If Channel goes down (even while other channels to the same node remain up), the monitor fires a DOWN with reason noconnection. This is partisan-specific behaviour — disterl has a single connection per pair of nodes and therefore no per-channel concept.

Options

{channel, Channel}
The channel to bind the monitor to. Defaults to the partisan default channel.
{channel_fallback, boolean()}
If the requested channel is not connected at monitor establishment, whether to fall back to the default channel for the establishment RPC. Defaults to true when Channel is the default channel and false otherwise — the explicit-channel default avoids silently splitting the user's traffic and the DOWN signal across two connections, which would break the FIFO guarantee above.

Failure

notalive
The partisan_monitor server is not running.
not_implemented
The active partisan peer service manager does not support the capabilities required for monitoring.
badarg
Process is not a valid partisan remote pid or registered-name reference, or Opts contains a malformed option.

monitor_node(Node, Flag)

-spec monitor_node(node() | partisan:node_spec(), boolean()) -> true.

Monitor the status of the node Node. If Flag is true, monitoring is turned on. If Flag is false, monitoring is turned off.

Making several calls to monitor_node(Node, true) for the same Node is not an error; it results in as many independent monitoring instances as the number of different calling processes i.e. If a process has made two calls to monitor_node(Node, true) and Node terminates, only one nodedown message is delivered to the process (this differs from erlang:monitor_node/2).

If Node fails or does not exist, the message {nodedown, Node} is delivered to the calling process. If there is no connection to Node, a nodedown message is delivered. As a result when using a membership strategy that uses a partial view, you cannot monitor nodes that are not members of the view.

Failure:

  • notalive if the partisan_monitor process is not alive.
  • not_implemented if the partisan peer service manager does not support the required capabilities required for monitoring.
  • badarg if any of the arguments is invalid.

This function is executed in the calling process.

monitor_nodes(Flag, Opts0)

-spec monitor_nodes(Flag :: boolean(), [partisan:monitor_nodes_opt()]) ->
                       ok | error | {error, notalive | not_implemented | badarg}.

Subscribe (or unsubscribe) the calling process to node status change messages. While subscribed, a {nodeup, Node} message is delivered when a new node is connected and a {nodedown, Node} message is delivered when a node is disconnected. If nodedown_reason is in Opts the extended forms {nodeup, Node, InfoList} / {nodedown, Node, InfoList} are delivered instead.

If Flag is true a new subscription is started. If Flag is false all subscriptions previously started with the same Opts are stopped. Two option lists are considered equivalent if they contain the same set of options.

Ordering with respect to disterl

Partisan delivers these signals in line with the disterl guarantees, with one important caveat:

  • nodeup is fired before any message can flow over the newly-established connection (the receiver-process for the new connection is started after the up callbacks run).
  • nodedown is fired only after every message already received on the dying connection has been placed in its destination process's mailbox. The receiver process delivers messages synchronously (erlang:send) and only then exits, and the down callbacks run inline in the manager's exit handler, so the runtime serialises these naturally.
  • Caveat: a partisan node-pair can have multiple channels. {nodeup, Node} / {nodedown, Node} fire when the first/last channel is up/down, but a process monitoring on a specific non-default channel may see its monitor's DOWN before the node-level nodedown (because that channel went down while the node remained reachable on others). For per-channel correctness use monitor/2 with {channel, _}.

Options

{node_type, all | visible | hidden}
Filter the subscription. hidden is a no-op since partisan does not have hidden nodes. Defaults to all.
nodedown_reason
Deliver the extended 3-tuple form with a reason in the InfoList.

This function is executed in the calling process.

start_link()

Starts the partisan_monitor server.

There is one partisan_monitor server instance per node.

terminate(Reason, State)