https://github.com/team-telnyx/pogo
Distributed supervisor for clustered Elixir applications
https://github.com/team-telnyx/pogo
distributed elixir supervisor
Last synced: 4 months ago
JSON representation
Distributed supervisor for clustered Elixir applications
- Host: GitHub
- URL: https://github.com/team-telnyx/pogo
- Owner: team-telnyx
- License: lgpl-3.0
- Created: 2023-03-31T12:27:33.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2023-10-03T08:44:20.000Z (over 2 years ago)
- Last Synced: 2025-09-30T19:43:14.836Z (9 months ago)
- Topics: distributed, elixir, supervisor
- Language: Elixir
- Homepage:
- Size: 53.7 KB
- Stars: 103
- Watchers: 9
- Forks: 3
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Pogo
Pogo is a distributed supervisor for clustered Elixir applications.
It uses battle-tested distributed named process groups (`:pg`) under the hood to maintain cluster-wide state and coordinate work between local supervisors running on different nodes.
Features of distributed supervisor:
* automatically chooses a node to locally supervise child process
* a child process running in the cluster can be started or stopped using any local supervisor
* ensures a child is started only once in the cluster (as long as its child spec is unique)
* redistibutes children when cluster topology changes
You can read more in an [introductory article](https://szajbus.dev/elixir/2023/05/22/pogo-distributed-supervisor-for-elixir.html).
## Installation
The package can be installed by adding `pogo` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:pogo, "~> 0.3.0"}
]
end
```
## Documentation
Full documentation can be found at [hexdocs.pm/pogo](https://hexdocs.pm/pogo).
## Example usage
Let's imagine we have an application running on multiple nodes that needs to monitor some external services and we want each of these services to be monitored only once.
Start `Pogo.DynamicSupervisor` under application's supervision tree, locally on each node. All these local supervisors will form a distributed supervisor named `MyApp.DistributedSupervisor`.
```elixir
defmodule MyApp.Application do
use Application
@impl true
def start(_type, _args) do
children = [
{Pogo.DynamicSupervisor, [name: MyApp.DistributedSupervisor, scope: :my_app]}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
```
Now request service monitor processes to be started as children of our distributed supervisor. It can be done on any of the nodes or even on all of them, the distributed supervisor will determine which of the local ones will actually start each child.
```elixir
for service_ip <- ["10.0.0.1", "10.0.0.2", "10.0.0.3"] do
Pogo.DynamicSupervisor.start_child(
MyApp.DistributedSupervisor,
%{
id: {MyApp.ServiceMonitor, service_ip},
start: {MyApp.ServiceMonitor, :start_link, [ip: service_ip]}
}
)
end
```
We can list locally and globally supervised child processes.
```elixir
Pogo.DynamicSupervisor.which_children(MyApp.DistributedSupervisor, :local)
# [{MyApp.ServiceMonitor, "10.0.0.2"}, #PID<0.2010.0>, :worker, [MyApp.ServiceMonitor]]
Pogo.DynamicSupervisor.which_children(MyApp.DistributedSupervisor, :global)
# [
# {MyApp.ServiceMonitor, "10.0.0.2"}, #PID<0.2010.0>, :worker, [MyApp.ServiceMonitor],
# {MyApp.ServiceMonitor, "10.0.0.1"}, #PID<4461.199.10>, :worker, [MyApp.ServiceMonitor],
# {MyApp.ServiceMonitor, "10.0.0.3"}, #PID<306.320.94>, :worker, [MyApp.ServiceMonitor]
# ]
```
To request a child to be terminated, its id needs to be provided. The request can be made on any of the nodes irrespective of whether the child is supervised locally or not.
```elixir
Pogo.DynamicSupervisor.terminate_child(
MyApp.DistributedSupervisor,
{MyApp.ServiceMonitor, "10.0.0.3"}
)
```
## Acknowledgments
Original version of this library was developed by [Guilherme Balena Versiani](https://github.com/balena).
## License
GNU Lesser General Public License v3.0, see [`LICENSE`](LICENSE) for details.