portunus_affinity behaviour (portunus v0.14.0)

View Source

An affinity strategy gives each portunus node (cluster member) a score for a key, and portunus_machine succession promotes the highest-scoring contender. Ties are broken in favor of the node that joined the succession queue first.

Two strategies are supported:

  • deterministic: a pure function of the key and the cluster members, so every node computes the same ranking. Built-in variants: fifo, pinned, preferred, hash
  • dynamic: a node scores itself from local state that it calculates dynamically, such as metrics (load, resource consumption, and so on). Built-in variants: metric, random

A score is computed by the contender at enqueue time and travels in the acquire command. While a contender waits, portunus_election recomputes the score at the reconcile cadence (a third of the lease TTL) and re-submits its bid when the score changed, so promotion ranks on scores at most one reconcile interval old. Direct users of acquire_or_join_succession_queue/5 get no automatic refresh: their score stays as submitted until they re-acquire.

A jittery dynamic strategy costs one command per queued key per reconcile interval, so keep the reported score quantized: report coarse integers that change when placement should, not raw samples. The built-in metric strategy already does.

Affinity strategies are passed around as a spec() that carries a short name (fifo, pinned, random, and so on). To use a custom module, pass a {Module, Args} tuple where Module implements the kind/0 and score/3 callbacks.

Summary

Functions

This node's score for Key, given the current cluster Members.

Types

spec()

-type spec() :: default | {strategy() | module(), term()} | fun((term(), [node()]) -> integer()).

strategy()

-type strategy() :: fifo | pinned | preferred | hash | metric | random.

Callbacks

kind()

-callback kind() -> deterministic | dynamic.

score(Key, Members, Args)

-callback score(Key :: term(), Members :: [node()], Args :: term()) -> integer().

Functions

kind/1

-spec kind(spec()) -> deterministic | dynamic.

score(Key, Members, Args)

-spec score(spec(), term(), [node()]) -> integer().

This node's score for Key, given the current cluster Members.