{"id":19134584,"url":"https://github.com/zenneriot/maracuja","last_synced_at":"2025-07-10T01:38:23.494Z","repository":{"id":57520879,"uuid":"184591855","full_name":"ZennerIoT/maracuja","owner":"ZennerIoT","description":"Spawn processes once per cluster, cope with net-splits","archived":false,"fork":false,"pushed_at":"2022-07-01T22:42:45.000Z","size":11,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-12T10:46:40.679Z","etag":null,"topics":["distributed-systems","elixir-lang","singleton-pattern"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZennerIoT.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-02T14:04:56.000Z","updated_at":"2022-07-01T22:42:48.000Z","dependencies_parsed_at":"2022-09-26T18:01:05.111Z","dependency_job_id":null,"html_url":"https://github.com/ZennerIoT/maracuja","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ZennerIoT/maracuja","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZennerIoT%2Fmaracuja","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZennerIoT%2Fmaracuja/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZennerIoT%2Fmaracuja/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZennerIoT%2Fmaracuja/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZennerIoT","download_url":"https://codeload.github.com/ZennerIoT/maracuja/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZennerIoT%2Fmaracuja/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259879583,"owners_count":22925792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-systems","elixir-lang","singleton-pattern"],"created_at":"2024-11-09T06:27:19.462Z","updated_at":"2025-06-14T20:32:30.024Z","avatar_url":"https://github.com/ZennerIoT.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Maracuja\n\nA microlibrary that helps you spawn a process that lives at most once per cluster.\n\nIt can cope with netsplits by checking if the count of the currently connected nodes \nwould have an _absolute_ majority in the historically biggest known cluster size.\n\n## How it handles net splits\n\nWith an exemplary amount of 5 nodes in a healthy cluster, imagine the following \nsplit scenarios:\n\n`5`: No split - one of the nodes will host the singleton\n\n`4 - 1`: The cluster with 4 nodes will host the singleton\n\n`3 - 2`: The cluster with 3 nodes will host the singleton\n\n`1 - 2 - 2`: None of the clusters will host the singleton because none of \nthem have an absolute majority\n\n`1 - 2 - 1 - 1`: Even though the cluster with 2 nodes would have the majority, \nit doesn't know that it's the cluster with the most nodes, so it doesn't \nhost the singleton\n\n`1 - 1 - 1 - 1 - 1`: None of these nodes will host the singleton either\n\nAs you can see, it is possible that in some net split situations, it is possible\nthat no singleton is hosted. As such, this library is not for you if you often\nexperience net splits and don't recover quickly from them.\n\n## Usage\n\nIn the `start_link` callback of your GenServer, instead of directly using the `GenServer` module to start the server, use `Maracuja.start_link/3`:\n\nThe `Maracuja` will call your module with `start_server/2` when it has decided to start the module in this \ncluster.\n\n```elixir\ndef MySingleton do\n  use GenServer\n\n  def start_link(args) do\n    Maracuja.start_link(__MODULE__, args, :my_global_name)\n  end\n\n  def start_server(args, name) do\n    GenServer.start_link(__MODULE__, args, name: name)\n  end\n\n  # init and rest of the server\nend\n```\n\nMaracuja uses `:global` to register the name, so you can find the pid of a singleton by passing its name to \n`:global.whereis_name`:\n\n```elixir\niex\u003e :global.whereis_name(:my_global_name)\n#Pid\u003c0.170.0\u003e\n```\n\nIn the case the cluster is experiencing a net split and the current node is part of a faction that's too small, `whereis_name` will return `:undefined`!\n\n## Planned features\n\n - [x] Support for other behaviours \n - [ ] Maybe support for other coping strategies\n\n## Installation\n\nThe package can be installed by adding `maracuja` \nto your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:maracuja, \"~\u003e 0.2.0\"}\n  ]\nend\n```\n\nDocumentation can be found at [https://hexdocs.pm/maracuja](https://hexdocs.pm/maracuja).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenneriot%2Fmaracuja","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzenneriot%2Fmaracuja","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenneriot%2Fmaracuja/lists"}