group_registry

Groups that can be joined and left by processes, and the members of which can be listed on request. This may be useful for publish-subscribe patterns, where many processes want to receive messages another.

This module is implemented using Erlang’s pg module and uses ETS for storage, so listing the members of a group is optimised for speed.

Groups are tracked by group registry processes, which you should add to your supervision tree. Each registry is independant from each other.

If a member terminates, it is automatically removed from the group.

If a group registry terminates the groups are lost and will need to be recreated. Restarting the group registry will not recover the groups.

There is no memory cost to the registry of a group without any members.

Publish-subscribe

This module is useful for pubsub, but it does not offer any functions for sending messages itself. To perform pubsub add the subscriber messages to a group, then the publishers can use the members function to get a list of subjects for the subscribers and send messages to them.

Distributed groups

If two nodes in an Erlang cluster have process registries or pg instances created with the same name (called a “scope” in the pg documentation) they will share group membership in an eventually consistent way. See the pg documentation for more information. Note that names created with the process.new_name are unique, so calling that function with the same prefix string on each node in an Erlang cluster will result in distinct names.

Scalability

Inserting members or getting all the members of a group pg is fast, but removing members from large groups with thousands of members in them is much slower. This module is best suited to numerous small groups.

If you need larger groups and members to be removed or to terminate frequently you may want to experiment with other registries. Always benchmark and profile your code when performance matters.

Types

A reference to the group registry process.

The type parameter is a message type that processes registered with the registry can be sent.

pub type GroupRegistry(message)

The message type that the registry accepts. This type is opaque and cannot be constructed directly. Instead use the functions in this module to interact with the registry.

The type parameter is a message type that processes registered with the registry can be sent.

pub type Message(message)

Values

pub fn get_registry(
  name: process.Name(Message(message)),
) -> GroupRegistry(message)
pub fn join(
  registry: GroupRegistry(message),
  group: String,
  new_member: process.Pid,
) -> process.Subject(message)

Add a process to a group.

A process can join a group many times and must then leave the group the same number of times.

A subject is returned which can be used to send to messages to the member, or for the member to receive messages.

pub fn leave(
  registry: GroupRegistry(message),
  group: String,
  members: List(process.Pid),
) -> Nil

Remove the given processes from the group, if they are members.

pub fn members(
  registry: GroupRegistry(message),
  group: String,
) -> List(process.Subject(message))

Returns subjects for all processes in the group. They are returned in no specific order.

If a process joined the group multiple times it will be present in the list that number of times.

pub fn start(
  name: process.Name(Message(message)),
) -> Result(
  actor.Started(GroupRegistry(message)),
  actor.StartError,
)

Start the registry with the given name. You likely want to use the supervised function instead, to add the registry to your supervision tree, but this may still be useful in your tests.

Remember that names must be created at the start of your program, and must not be created dynamically such as within your supervision tree (it may restart, creating new names) or in a loop.

pub fn supervised(
  name: process.Name(Message(message)),
) -> supervision.ChildSpecification(GroupRegistry(message))

A specification for starting the registry under a supervisor, using the given name. You should likely use this function in applications.

Remember that names must be created at the start of your program, and must not be created dynamically such as within your supervision tree (it may restart, creating new names) or in a loop.

Search Document