{"id":18135490,"url":"https://github.com/whitfin/local-cluster","last_synced_at":"2025-05-16T11:04:13.627Z","repository":{"id":47447374,"uuid":"151816868","full_name":"whitfin/local-cluster","owner":"whitfin","description":"Easy local cluster creation for Elixir to aid in unit testing","archived":false,"fork":false,"pushed_at":"2024-09-01T08:23:03.000Z","size":56,"stargazers_count":227,"open_issues_count":4,"forks_count":31,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-09T14:03:05.586Z","etag":null,"topics":["distributed-computing","erlang-distribution","local-clustering","unit-testing"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/whitfin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-06T07:46:45.000Z","updated_at":"2025-01-18T17:18:53.000Z","dependencies_parsed_at":"2023-12-29T22:24:07.357Z","dependency_job_id":"a28ccea1-b14a-453d-8e6b-9eef92a964b3","html_url":"https://github.com/whitfin/local-cluster","commit_stats":{"total_commits":47,"total_committers":6,"mean_commits":7.833333333333333,"dds":0.1063829787234043,"last_synced_commit":"e0b298f3fddb693898b89db73c9957eb542c3217"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Flocal-cluster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Flocal-cluster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Flocal-cluster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Flocal-cluster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/whitfin","download_url":"https://codeload.github.com/whitfin/local-cluster/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254518384,"owners_count":22084374,"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-computing","erlang-distribution","local-clustering","unit-testing"],"created_at":"2024-11-01T14:07:51.844Z","updated_at":"2025-05-16T11:04:13.602Z","avatar_url":"https://github.com/whitfin.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LocalCluster\n[![Build Status](https://img.shields.io/github/actions/workflow/status/whitfin/local-cluster/ci.yml?branch=main)](https://github.com/whitfin/local-cluster/actions) [![Coverage Status](https://img.shields.io/coveralls/whitfin/local-cluster.svg)](https://coveralls.io/github/whitfin/local-cluster) [![Hex.pm Version](https://img.shields.io/hexpm/v/local_cluster.svg)](https://hex.pm/packages/local_cluster) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://hexdocs.pm/local_cluster/)\n\nThis library is designed to assist in testing distributed states in Elixir\nwhich require a number of local nodes.\n\nThe aim is to provide a small set of functions which hide the complexity of\nspawning local nodes, as well as providing the ease of cleaning up the started\nnodes. The entire library is simple shimming around the Erlang APIs for dealing\nwith distributed nodes, As some of it is non-obvious, and as I need this code\nfor several projects, I span it out as a smaller project.\n\n## Installation\n\nTo install it for your project, you can pull it directly from Hex. Rather\nthan use the version shown below, you can use the the latest version from\nHex (shown at the top of this README).\n\n```elixir\ndef deps do\n  [{:local_cluster, \"~\u003e 2.0\", only: [:test]}]\nend\n```\n\nDocumentation and examples can be found on [Hexdocs](https://hexdocs.pm/local_cluster/)\nas they're updated automatically alongside each release. Note that you should only\nuse the `:test` flag in your dependency if you're not using it for other environments.\n\n## Setup\n\nTo configure your test suites for cluster testing, you need to run through a one-time\nsetup to change some stuff in your `test_helper.exs`. This is required to avoid some\npotential issues with your node name changing after your application tree has already\nstated. This also reduces some bloat due to having `LocalCluster.start/0` in most test\ncases. The snippet below can be used as a sample helper file. Make sure to change the\napplication name to match your application name.\n\n```elixir\n# start the current node as a manager\n:ok = LocalCluster.start()\n\n# start your application tree manually\nApplication.ensure_all_started(:my_app)\n\n# run all tests!\nExUnit.start()\n```\n\nYou will also need to pass the `--no-start` flag to `mix test`. Fortunately this is\neasy enough, as you can add an alias in your `mix.exs` to do this automatically:\n\n```elixir\ndef project do\n  [\n    # ...\n    aliases: [\n      test: \"test --no-start\"\n    ]\n    # ...\n  ]\nend\n```\n\nThis library itself uses this setup, so you can copy/paste as needed or use as an\nexample when integrating into your own codebase. Note that you must have ensured\nthat `epmd` has been started before using this lib; typically with `epmd -daemon`.\n\n## Usage\n\nAs mentioned above, the API is deliberately _tiny_ to make it easier to use this\nlibrary when testing. Below is an example of using this library to spawn a set of\nchild nodes for testing:\n\n```elixir\ndefmodule MyTest do\n  use ExUnit.Case\n\n  test \"creates and stops child nodes\" do\n    # create a new cluster of 3 nodes\n    {:ok, cluster} = LocalCluster.start_link(3)\n\n    # fetch the list of nodes contained in the cluster\n    {:ok, [node1, node2, node3]} = LocalCluster.nodes(cluster)\n\n    # check that all nodes respond\n    assert Node.ping(node1) == :pong\n    assert Node.ping(node2) == :pong\n    assert Node.ping(node3) == :pong\n\n    # stop a single node in our cluster\n    :ok = LocalCluster.stop(cluster, node1)\n\n    # check that node does not respond\n    assert Node.ping(node1) == :pang\n    assert Node.ping(node2) == :pong\n    assert Node.ping(node3) == :pong\n\n    # stop the entire cluster\n    :ok = LocalCluster.stop(cluster)\n\n    # check that no nodes respond\n    assert Node.ping(node1) == :pang\n    assert Node.ping(node2) == :pang\n    assert Node.ping(node3) == :pang\n  end\nend\n```\n\nAfter calling `start_link/2` you will receive a process identifier which can be used\nto fetch a list of spawned nodes to communicate with via RPC (or whatever you like).\nAlthough these nodes are automatically cleaned up when the calling process dies, you\ncan manually stop nodes to test disconnection within a test.\n\n## Options\n\nThere are various options supported when creating a cluster, here are most of them\nwith a few notes about what they're for and what they do:\n\n```elixir\nLocalCluster.start_link(3, [\n  # Allows the caller to determine startup order of bundled applications,\n  # and allows you to exclude applications from the startup sequence. If\n  # this option is not provided, the default behaviour will be to match\n  # the startup sequence of the local node. Each of these applications\n  # will be loaded with all dependencies via `Application.ensure_all_started/2`.\n  applications: [\n    :start_this_application,\n    :and_then_this_one\n  ],\n\n  # Similar to the above; if you need to override the application environment\n  # inherited by your cluster nodes, you can use the `:environment` option to\n  # merge values _over_ the environment inside the started nodes.\n  environment: [\n    my_app: [\n      port: 9999\n    ]\n  ],\n\n  # Enables loading any additional files onto the remote notes, by providing\n  # an absolute file path to compile inside the cluster. This is necessary if\n  # you wish to spawn tasks onto the cluster from inside your test code, as\n  # test code is not loaded automatically.\n  files: [\n    __ENV__.file\n  ],\n\n  # Enables naming and registration of the cluster PID. If this value is\n  # not provided the cluster is reachable only by PID.\n  name: :my_cluster,\n\n  # Enables a custom node name prefix for members of the cluster. If this\n  # is not provided it will default to the value of `:name`. If that flag\n  # is also not provided, a random string will be generated.\n  prefix: \"\"\n])\n```\n\n## Migration to v2\n\nIf you previously used this module on the v1.x line, a few things have changed\nwithin the API to make it more consistent and Elixir-y (hopefully). The following\nexamples should show how you can map over to the new API easily:\n\n```elixir\n# starting a cluster in v1.x\nnodes = LocalCluster.start_nodes(\"my-cluster\", 3, [\n  # options...\n])\n\n# stopping a cluster in v1.x\nLocalCluster.stop_nodes(nodes)\n\n# starting a cluster in v2.x\n{:ok, cluster} = LocalCluster.start_link(3, [\n  prefix: \"my_cluster\"\n])\n{:ok, nodes} = LocalCluster.nodes(cluster)\n\n# stopping a cluster in v2.x\nLocalCluster.stop(cluster)\n```\n\nHopefully even though this is a major bump it's not very disruptive. Unfortunately\nthere was no reliable way to keep the old API, as frequent use in `ExUnit` meant\nthat we can't use the process dictionary to store the cluster name.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitfin%2Flocal-cluster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwhitfin%2Flocal-cluster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitfin%2Flocal-cluster/lists"}