# Module cpg

- Description
- Data Types
- Function Index
- Function Details

### CloudI Process Groups (CPG)

cpg relies on distributed Erlang for node communication, which means a fully connected network topology is created.

Copyright © 2011-2020 Michael Truog

Version: 2.0.1 Nov 26 2020 15:22:42 ------------------------------------------------------------------------

Behaviours: `gen_server`.

Authors: Michael Truog (`mjtruog at protonmail dot com`).

## Description

### CloudI Process Groups (CPG)

cpg relies on distributed Erlang for node communication, which means a fully connected network topology is created. With Distributed Erlang, Erlang pids either exist on the local node or a remote node (which shares a connection with the local node, so only 1 node hop is necessary in the worst case).

## Data Types

### callback()

`callback() = callback_join() | callback_leave()`

### callback_join()

`callback_join() = fun((any(), pid()) -> any()) | fun((any(), pid(), reason_join()) -> any())`

### callback_leave()

`callback_leave() = fun((any(), pid()) -> any()) | fun((any(), pid(), reason_leave()) -> any())`

### listen()

`listen() = visible | all`

### name()

`name() = any()`

### reason_join()

`reason_join() = join_local | join_remote`

### reason_leave()

`reason_leave() = leave_local | leave_remote | {exit, any()}`

### scope()

`scope() = atom()`

### via_name()

`via_name() = {global, scope(), name(), random} | {global, scope(), name(), oldest} | {global, scope(), name(), pos_integer()} | {local, scope(), name(), random} | {local, scope(), name(), oldest} | {local, scope(), name(), pos_integer()} | {global, scope(), name()} | {local, scope(), name()} | {global, name(), pos_integer()} | {local, name(), pos_integer()} | {global, name()} | {local, name()} | {scope(), name()} | {name(), pos_integer()} | name()`

for OTP behaviors

## Function Index

add_join_callback/2 | #### Add a join callback. .
add_join_callback/3 | #### Add a join callback. .
add_leave_callback/2 | #### Add a leave callback. .
add_leave_callback/3 | #### Add a leave callback. .
create/1 | #### Create a group explicitly no-op. .
create/2 | #### Create a group explicitly in a specific scope no-op. .
create/3 | #### Create a group explicitly in a specific scope no-op. .
delete/1 | #### Delete a group explicitly no-op. .
delete/2 | #### Delete a group explicitly in a specific scope no-op. .
delete/3 | #### Delete a group explicitly in a specific scope no-op. .
get_closest_pid/1 | #### Get a group member, with local pids given priority. .
get_closest_pid/2 | #### Get a group member, with local pids given priority while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_closest_pid/3 | #### Get a group member within a specific scope, with local pids given priority while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_closest_pid/4 | #### Get a group member within a specific scope, with local pids given priority while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_furthest_pid/1 | #### Get a group member, with remote pids given priority. .
get_furthest_pid/2 | #### Get a group member, with remote pids given priority while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_furthest_pid/3 | #### Get a group member within a specific scope, with remote pids given priority while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_furthest_pid/4 | #### Get a group member within a specific scope, with remote pids given priority while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_members/1 | #### Get only the local members of a specific group. All members are ordered from newest to oldest, based on the join order, not pid creation time.
get_local_members/2 | #### Get only the local members of a specific group while excluding a specific pid or within a specific scope. All members are ordered from newest to oldest, based on the join order, not pid creation time.
get_local_members/3 | #### Get only the local members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the join order, not pid creation time.
get_local_members/4 | #### Get only the local members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the join order, not pid creation time.
get_local_newest_pid/1 | #### Get the newest local group member. .
get_local_newest_pid/2 | #### Get the newest local group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_local_newest_pid/3 | #### Get the newest local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_newest_pid/4 | #### Get the newest local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_oldest_pid/1 | #### Get the oldest local group member. .
get_local_oldest_pid/2 | #### Get the oldest local group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_local_oldest_pid/3 | #### Get the oldest local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_oldest_pid/4 | #### Get the oldest local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_pid/1 | #### Get a local group member. .
get_local_pid/2 | #### Get a local group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_local_pid/3 | #### Get a local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_local_pid/4 | #### Get a local group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_members/1 | #### Get the members of a specific group. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_members/2 | #### Get the members of a specific group while excluding a specific pid or within a specific scope. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_members/3 | #### Get the members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_members/4 | #### Get the members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_newest_pid/1 | #### Get the newest group member. .
get_newest_pid/2 | #### Get the newest group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_newest_pid/3 | #### Get the newest group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_newest_pid/4 | #### Get the newest group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_oldest_pid/1 | #### Get the oldest group member. .
get_oldest_pid/2 | #### Get the oldest group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_oldest_pid/3 | #### Get the oldest group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_oldest_pid/4 | #### Get the oldest group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_random_pid/1 | #### Get a group member. .
get_random_pid/2 | #### Get a group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_random_pid/3 | #### Get a group member within a specific scope while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_random_pid/4 | #### Get a group member within a specific scope while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_members/1 | #### Get only the remote members of a specific group. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_remote_members/2 | #### Get only the remote members of a specific group while excluding a specific pid or within a specific scope. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_remote_members/3 | #### Get only the remote members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_remote_members/4 | #### Get only the remote members of a specific group within a specific scope while excluding a specific pid. All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).
get_remote_newest_pid/1 | #### Get the newest remote group member. .
get_remote_newest_pid/2 | #### Get the newest remote group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_remote_newest_pid/3 | #### Get the newest remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_newest_pid/4 | #### Get the newest remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_oldest_pid/1 | #### Get the oldest remote group member. .
get_remote_oldest_pid/2 | #### Get the oldest remote group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_remote_oldest_pid/3 | #### Get the oldest remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_oldest_pid/4 | #### Get the oldest remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_pid/1 | #### Get a remote group member. .
get_remote_pid/2 | #### Get a remote group member while excluding a specific pid or within a specific scope. Usually the self() pid is excluded with this function call.
get_remote_pid/3 | #### Get a remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
get_remote_pid/4 | #### Get a remote group member within a specific scope, while excluding a specific pid. Usually the self() pid is excluded with this function call.
hidden_nodes/1 | #### Get the hidden nodes. .
ignore_node/2 | #### Check if a node is ignored. Nodes that connect periodically for running operations commands are ignored by this function.
join/1 | #### Join a specific group with self() as a local pid. A group is automatically created if it does not already exist.
join/2 | #### Join a specific group with the specified local pid or a specific group within a specific scope with self() as a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
join/3 | #### Join a specific group within a specific scope with a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
join/4 | #### Join a specific group within a specific scope with a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
join_count/1 | #### Provide a count of the previous joins of a specific group with self(). .
join_count/2 | #### Provide a count of the previous joins of a specific group with a specific pid. .
join_count/3 | #### Provide a count of the previous joins of a specific group with a specific pid. .
join_count/4 | #### Provide a count of the previous joins of a specific group with a specific pid. .
join_counts/1 | #### Join specific groups a specific number of times. .
join_counts/2 | #### Join specific groups a specific number of times. .
join_counts/3 | #### Join specific groups a specific number of times. .
join_counts/4 | #### Join specific groups a specific number of times. .
leave/0 | #### Leave all groups. .
leave/1 | #### Leave a specific group or all groups with a local pid. The group is automatically removed if it becomes empty.
leave/2 | #### Leave a specific group or all groups with the specified local pid or a specific group within a specific scope with self() as a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
leave/3 | #### Leave a specific group or all groups within a specific scope with a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
leave/4 | #### Leave a specific group or all groups within a specific scope with a local pid. The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups.
leave_counts/1 | #### Leave specific groups a specific number of times. .
leave_counts/2 | #### Leave specific groups a specific number of times. .
leave_counts/3 | #### Leave specific groups a specific number of times. .
leave_counts/4 | #### Leave specific groups a specific number of times. .
listen_nodes/2 | #### Get the monitored listen nodes. .
register_name/2 | #### Function to provide via process registration functionality. Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()}).
remove_join_callback/2 | #### Remove a join callback. .
remove_join_callback/3 | #### Remove a join callback. .
remove_leave_callback/2 | #### Remove a leave callback. .
remove_leave_callback/3 | #### Remove a leave callback. .
reset/1 | #### Reset any internal scope state. Updates cpg application node_type monitoring.
reset_all/1 | #### Reset internal scopes state. Updates cpg application node_type monitoring.
scope_exists/1 | #### Confirm a scope exists. .
send/2 | #### Function to provide via process registration functionality. Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()}).
start_link/0 | #### Start process groups storage for the default scope. .
start_link/1 | #### Start process groups storage for a specific scope. .
unregister_name/1 | #### Function to provide via process registration functionality. Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()}).
valid_node/1 | #### Check if a node is valid. If the node name is not ignored.
visible_nodes/1 | #### Get the visible nodes. .
whereis_name/1 | #### Function to provide via process registration functionality. Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()}).
which_groups/0 | #### Get all the groups currently defined. .
which_groups/1 | #### Get all the groups currently defined within a specific scope. .
which_groups/2 | #### Get all the groups currently defined within a specific scope. .
which_groups/3 | #### Get all the groups currently defined within a specific scope. .
which_groups_counts/1 | #### Get the join_count of each group a process has joined. .
which_groups_counts/2 | #### Get the join_count of each group a process has joined. .
which_groups_counts/3 | #### Get the join_count of each group a process has joined. .

## Function Details

### add_join_callback/2

`add_join_callback(GroupName::name(), F::callback_join()) -> ok`

#### Add a join callback.

### add_join_callback/3

`add_join_callback(Scope::scope(), GroupName::name(), F::callback_join()) -> ok`

#### Add a join callback.

### add_leave_callback/2

`add_leave_callback(GroupName::name(), F::callback_leave()) -> ok`

#### Add a leave callback.

### add_leave_callback/3

`add_leave_callback(Scope::scope(), GroupName::name(), F::callback_leave()) -> ok`

#### Add a leave callback.

### create/1

`create(X1::name()) -> ok`

#### Create a group explicitly no-op.

### create/2

`create(X1::scope(), X2::name()) -> ok`

#### Create a group explicitly in a specific scope no-op.

### create/3

`create(X1::scope(), X2::name(), X3::pos_integer() | infinity) -> ok`

#### Create a group explicitly in a specific scope no-op.

### delete/1

`delete(X1::name()) -> ok`

#### Delete a group explicitly no-op.

### delete/2

`delete(X1::scope(), X2::name()) -> ok`

#### Delete a group explicitly in a specific scope no-op.

### delete/3

`delete(X1::scope(), X2::name(), X3::pos_integer() | infinity) -> ok`

#### Delete a group explicitly in a specific scope no-op.

### get_closest_pid/1

`get_closest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member, with local pids given priority.

### get_closest_pid/2

`get_closest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member, with local pids given priority while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_closest_pid/3

`get_closest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope, with local pids given priority while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_closest_pid/4

`get_closest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope, with local pids given priority while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_furthest_pid/1

`get_furthest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member, with remote pids given priority.

### get_furthest_pid/2

`get_furthest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member, with remote pids given priority while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_furthest_pid/3

`get_furthest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope, with remote pids given priority while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_furthest_pid/4

`get_furthest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope, with remote pids given priority while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_members/1

`get_local_members(GroupName::name()) -> cpg_data:get_members_return()`

#### Get only the local members of a specific group.

All members are ordered from newest to oldest, based on the join order, not pid creation time.

### get_local_members/2

`get_local_members(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the local members of a specific group while excluding a specific pid or within a specific scope.

All members are ordered from newest to oldest, based on the join order, not pid creation time. Usually the self() pid is excluded with this function call.

### get_local_members/3

`get_local_members(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the local members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the join order, not pid creation time. Usually the self() pid is excluded with this function call.

### get_local_members/4

`get_local_members(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the local members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the join order, not pid creation time. Usually the self() pid is excluded with this function call.

### get_local_newest_pid/1

`get_local_newest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest local group member.

### get_local_newest_pid/2

`get_local_newest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest local group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_local_newest_pid/3

`get_local_newest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_newest_pid/4

`get_local_newest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_oldest_pid/1

`get_local_oldest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest local group member.

### get_local_oldest_pid/2

`get_local_oldest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest local group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_local_oldest_pid/3

`get_local_oldest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_oldest_pid/4

`get_local_oldest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_pid/1

`get_local_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a local group member.

### get_local_pid/2

`get_local_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a local group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_local_pid/3

`get_local_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_local_pid/4

`get_local_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a local group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_members/1

`get_members(GroupName::name()) -> cpg_data:get_members_return()`

#### Get the members of a specific group.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).

### get_members/2

`get_members(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get the members of a specific group while excluding a specific pid or within a specific scope.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_members/3

`get_members(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get the members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_members/4

`get_members(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get the members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_newest_pid/1

`get_newest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest group member.

### get_newest_pid/2

`get_newest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_newest_pid/3

`get_newest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_newest_pid/4

`get_newest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_oldest_pid/1

`get_oldest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest group member.

### get_oldest_pid/2

`get_oldest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_oldest_pid/3

`get_oldest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_oldest_pid/4

`get_oldest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_random_pid/1

`get_random_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member.

### get_random_pid/2

`get_random_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_random_pid/3

`get_random_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_random_pid/4

`get_random_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a group member within a specific scope while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_members/1

`get_remote_members(GroupName::name()) -> cpg_data:get_members_return()`

#### Get only the remote members of a specific group.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time).

### get_remote_members/2

`get_remote_members(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the remote members of a specific group while excluding a specific pid or within a specific scope.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_remote_members/3

`get_remote_members(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the remote members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_remote_members/4

`get_remote_members(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> cpg_data:get_members_return()`

#### Get only the remote members of a specific group within a specific scope while excluding a specific pid.

All members are ordered from newest to oldest, based on the group membership surviving netsplits (join order, not pid creation time). Usually the self() pid is excluded with this function call.

### get_remote_newest_pid/1

`get_remote_newest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest remote group member.

### get_remote_newest_pid/2

`get_remote_newest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest remote group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_remote_newest_pid/3

`get_remote_newest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_newest_pid/4

`get_remote_newest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the newest remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_oldest_pid/1

`get_remote_oldest_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest remote group member.

### get_remote_oldest_pid/2

`get_remote_oldest_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest remote group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_remote_oldest_pid/3

`get_remote_oldest_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_oldest_pid/4

`get_remote_oldest_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get the oldest remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_pid/1

`get_remote_pid(GroupName::name()) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a remote group member.

### get_remote_pid/2

`get_remote_pid(GroupName::name() | scope(), Exclude::pid() | name() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a remote group member while excluding a specific pid or within a specific scope.

Usually the self() pid is excluded with this function call.

### get_remote_pid/3

`get_remote_pid(Scope::scope() | name(), GroupName::name() | pid(), Exclude::pid() | pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### get_remote_pid/4

`get_remote_pid(Scope::scope(), GroupName::name(), Exclude::pid(), Timeout::pos_integer() | infinity) -> {ok, name(), pid()} | {error, cpg_data:get_pid_error_reason()}`

#### Get a remote group member within a specific scope, while excluding a specific pid.

Usually the self() pid is excluded with this function call.

### hidden_nodes/1

`hidden_nodes(NodeNameLocal::nonempty_string()) -> [node()]`

#### Get the hidden nodes.

### ignore_node/2

`ignore_node(Node::node(), NodeNameLocal::nonempty_string()) -> boolean()`

#### Check if a node is ignored.

Nodes that connect periodically for running operations commands are ignored by this function.

### join/1

`join(GroupName::name()) -> ok`

#### Join a specific group with self() as a local pid.

A group is automatically created if it does not already exist.

### join/2

`join(GroupName::name() | scope(), Pid::pid() | name()) -> ok`

#### Join a specific group with the specified local pid or a specific group within a specific scope with self() as a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. A group is automatically created if it does not already exist.

### join/3

`join(Scope::scope() | name(), GroupName::name() | pid(), Pid::pid() | pos_integer() | infinity) -> ok`

#### Join a specific group within a specific scope with a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. A group is automatically created if it does not already exist.

### join/4

`join(Scope::scope(), GroupName::name(), Pid::pid(), Timeout::pos_integer() | infinity) -> ok`

#### Join a specific group within a specific scope with a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. A group is automatically created if it does not already exist.

### join_count/1

`join_count(GroupName::name()) -> non_neg_integer()`

#### Provide a count of the previous joins of a specific group with self().

### join_count/2

`join_count(GroupName::name() | scope(), Pid::pid() | name()) -> non_neg_integer()`

#### Provide a count of the previous joins of a specific group with a specific pid.

### join_count/3

`join_count(Scope::scope() | name(), GroupName::name() | pid(), Pid::pid() | pos_integer() | infinity) -> non_neg_integer()`

#### Provide a count of the previous joins of a specific group with a specific pid.

### join_count/4

`join_count(Scope::scope(), GroupName::name(), Pid::pid(), Timeout::pos_integer() | infinity) -> non_neg_integer()`

#### Provide a count of the previous joins of a specific group with a specific pid.

### join_counts/1

`join_counts(Counts::[{name(), pos_integer()}]) -> ok | error`

#### Join specific groups a specific number of times.

### join_counts/2

`join_counts(Counts::[{name(), pos_integer()}] | scope(), Pid::pid() | [{name(), pos_integer()}]) -> ok | error`

#### Join specific groups a specific number of times.

### join_counts/3

`join_counts(Scope::scope() | [{name(), pos_integer()}], Counts::[{name(), pos_integer()}] | pid(), Pid::pid() | pos_integer() | infinity) -> ok | error`

#### Join specific groups a specific number of times.

### join_counts/4

`join_counts(Scope::scope(), Counts::[{name(), pos_integer()}], Pid::pid(), Timeout::pos_integer() | infinity) -> ok | error`

#### Join specific groups a specific number of times.

### leave/0

`leave() -> ok | error`

#### Leave all groups.

### leave/1

`leave(Pid::pid() | name()) -> ok | error`

#### Leave a specific group or all groups with a local pid.

The group is automatically removed if it becomes empty.

### leave/2

`leave(Scope::name() | scope() | pid(), Pid::pid() | name() | pos_integer() | infinity) -> ok | error`

#### Leave a specific group or all groups with the specified local pid or a specific group within a specific scope with self() as a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. The group will automatically be removed if it becomes empty.

### leave/3

`leave(Scope::scope() | name(), Pid::name() | pid(), Timeout::pid() | pos_integer() | infinity) -> ok | error`

#### Leave a specific group or all groups within a specific scope with a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. The group will automatically be removed if it becomes empty.

### leave/4

`leave(Scope::scope(), GroupName::name(), Pid::pid(), Timeout::pos_integer() | infinity) -> ok | error`

#### Leave a specific group or all groups within a specific scope with a local pid.

The pid must be a local pid to justify not using a distributed transaction since the cpg gen_server process acts like mutex lock, enforcing consistent local state for all local pid process groups. The group will automatically be removed if it becomes empty.

### leave_counts/1

`leave_counts(Counts::[{name(), pos_integer()}]) -> ok | error`

#### Leave specific groups a specific number of times.

### leave_counts/2

`leave_counts(Counts::[{name(), pos_integer()}] | scope(), Pid::pid() | [{name(), pos_integer()}]) -> ok | error`

#### Leave specific groups a specific number of times.

### leave_counts/3

`leave_counts(Scope::scope() | [{name(), pos_integer()}], Counts::[{name(), pos_integer()}] | pid(), Pid::pid() | pos_integer() | infinity) -> ok | error`

#### Leave specific groups a specific number of times.

### leave_counts/4

`leave_counts(Scope::scope(), Counts::[{name(), pos_integer()}], Pid::pid(), Timeout::pos_integer() | infinity) -> ok | error`

#### Leave specific groups a specific number of times.

### listen_nodes/2

`listen_nodes(Listen::listen(), NodeNameLocal::nonempty_string()) -> [node()]`

#### Get the monitored listen nodes.

### register_name/2

`register_name(GroupName::via_name(), Pid::pid()) -> yes`

#### Function to provide via process registration functionality.

Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()})

### remove_join_callback/2

`remove_join_callback(GroupName::name(), F::callback_join()) -> ok`

#### Remove a join callback.

### remove_join_callback/3

`remove_join_callback(Scope::scope(), GroupName::name(), F::callback_join()) -> ok`

#### Remove a join callback.

### remove_leave_callback/2

`remove_leave_callback(GroupName::name(), F::callback_leave()) -> ok`

#### Remove a leave callback.

### remove_leave_callback/3

`remove_leave_callback(Scope::scope(), GroupName::name(), F::callback_leave()) -> ok`

#### Remove a leave callback.

### reset/1

`reset(Scope::scope()) -> ok`

#### Reset any internal scope state.

Updates cpg application node_type monitoring

### reset_all/1

`reset_all(Scopes::[scope()]) -> ok`

#### Reset internal scopes state.

Updates cpg application node_type monitoring

### scope_exists/1

`scope_exists(Scope::atom()) -> ok | {error, any()}`

#### Confirm a scope exists.

### send/2

`send(ViaName::via_name(), Msg::any()) -> pid()`

#### Function to provide via process registration functionality.

Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()})

### start_link/0

`start_link() -> {ok, pid()} | {error, term()}`

#### Start process groups storage for the default scope.

### start_link/1

`start_link(Scope::atom()) -> {ok, pid()} | {error, term()}`

#### Start process groups storage for a specific scope.

### unregister_name/1

`unregister_name(GroupName::via_name()) -> ok | error`

#### Function to provide via process registration functionality.

Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()})

### valid_node/1

`valid_node(Node::node()) -> boolean()`

#### Check if a node is valid.

If the node name is not ignored.

### visible_nodes/1

`visible_nodes(NodeNameLocal::nonempty_string()) -> [node()]`

#### Get the visible nodes.

### whereis_name/1

`whereis_name(GroupName::via_name()) -> pid() | undefined`

#### Function to provide via process registration functionality.

Use within an OTP behavior by specifying {via, cpg, via_name()} for the process registration (instead of {local, atom()} or {global, atom()})

### which_groups/0

`which_groups() -> [name()]`

#### Get all the groups currently defined.

### which_groups/1

`which_groups(Scope::scope() | pid() | pos_integer() | infinity) -> [name()]`

#### Get all the groups currently defined within a specific scope.

### which_groups/2

`which_groups(Scope::scope() | pid(), Pid::pid() | pos_integer() | infinity) -> [name()]`

#### Get all the groups currently defined within a specific scope.

### which_groups/3

`which_groups(Scope::scope(), Pid::pid(), Timeout::pos_integer() | infinity) -> [name()]`

#### Get all the groups currently defined within a specific scope.

### which_groups_counts/1

`which_groups_counts(Pid::pid()) -> [{name(), pos_integer()}]`

#### Get the join_count of each group a process has joined.

### which_groups_counts/2

`which_groups_counts(Scope::scope() | pid(), Pid::pid() | pos_integer() | infinity) -> [{name(), pos_integer()}]`

#### Get the join_count of each group a process has joined.

### which_groups_counts/3

`which_groups_counts(Scope::scope(), Pid::pid(), Timeout::pos_integer() | infinity) -> [{name(), pos_integer()}]`

#### Get the join_count of each group a process has joined.

Generated by EDoc