{"id":13508824,"url":"https://github.com/whitfin/eternal","last_synced_at":"2025-05-15T23:06:08.932Z","repository":{"id":54357404,"uuid":"61170183","full_name":"whitfin/eternal","owner":"whitfin","description":"Keep your ETS tables running forever using bouncing GenServers","archived":false,"fork":false,"pushed_at":"2024-11-26T17:21:42.000Z","size":54,"stargazers_count":101,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T10:33:49.383Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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":"2016-06-15T02:11:21.000Z","updated_at":"2025-03-27T23:37:17.000Z","dependencies_parsed_at":"2024-05-01T17:21:05.027Z","dependency_job_id":"9c3c0574-8c76-44a1-8444-4b1d5c054ab2","html_url":"https://github.com/whitfin/eternal","commit_stats":{"total_commits":47,"total_committers":3,"mean_commits":"15.666666666666666","dds":0.5319148936170213,"last_synced_commit":"e9d0d1b43c9b7551e582190373a18c87a82bbf3d"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Feternal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Feternal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Feternal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitfin%2Feternal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/whitfin","download_url":"https://codeload.github.com/whitfin/eternal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254259310,"owners_count":22040810,"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":[],"created_at":"2024-08-01T02:00:59.050Z","updated_at":"2025-05-15T23:06:03.909Z","avatar_url":"https://github.com/whitfin.png","language":"Elixir","funding_links":[],"categories":["ORM and Datamapping"],"sub_categories":[],"readme":"# Eternal\n[![Build Status](https://img.shields.io/github/actions/workflow/status/whitfin/eternal/ci.yml?branch=main)](https://github.com/whitfin/eternal/actions) [![Coverage Status](https://img.shields.io/coveralls/whitfin/eternal.svg)](https://coveralls.io/github/whitfin/eternal) [![Hex.pm Version](https://img.shields.io/hexpm/v/eternal.svg)](https://hex.pm/packages/eternal) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://hexdocs.pm/eternal/)\n\nEternal is a simple way to monitor an ETS table to ensure that it never dies. It works by using bouncing GenServers to ensure that both an owner and heir are always available, via the use of scheduled monitoring and message passing. The idea is similar to that of the Immortal library, but taking it further to ensure a more bulletproof solution - and removing the need to have a single process dedicated to owning your ETS table.\n\n## Installation\n\nEternal is available on [Hex](https://hex.pm/). You can install the package by adding `eternal` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [{:eternal, \"~\u003e 1.2\"}]\nend\n```\n\nThen running `mix deps.get` will pull the package from the registry.\n\n## Usage\n\n### Manual Startup\n\nThe API of Eternal is quite small in order to reduce the risk of potential crashes (as that would cause you to lose your ETS tables). You'll probably just want to use `Eternal.start_link/3` which behaves quite similarly to `:ets.new/2`.\n\nThe first two arguments are identical to `:ets.new/2`, and the latter is just a Keyword List of options to configure Eternal. It should be noted that the table will always have the `:public` (for table access) and `:named_table` (for table naming) arguments passed in, whether specified or not. Both the second and third arguments are optional.\n\n```elixir\niex\u003e Eternal.start_link(:table1, [ :set, { :read_concurrency, true }])\n{ :ok, #PID\u003c0.402.0\u003e }\niex\u003e Eternal.start_link(:table2, [ :set, { :read_concurrency, true }], [ quiet: true ])\n{ :ok, #PID\u003c0.406.0\u003e }\n```\n\nFor further usage examples, please see the [documentation](https://hexdocs.pm/eternal/).\n\n### Application Supervision\n\nI'd highly recommend setting up an Application and letting Eternal start up inside the Supervision tree this way - just make sure that your strategy is `:one_for_one`, otherwise a crash in a different child in the tree would restart your ETS table.\n\n```elixir\ndefmodule MyApplication do\n  use Application\n\n  @impl true\n  def start(_type, _args) do\n    children = [\n      %{\n        id: Eternal,\n        start: {Eternal, :start_link, [:table, [:compressed], [quiet: true]]}\n      }\n    ]\n\n    # See https://hexdocs.pm/elixir/Supervisor.html\n    # for other strategies and supported options\n    opts = [strategy: :one_for_one]\n    Supervisor.start_link(children, opts)\n  end\nend\n```\n\nIf you need a strategy other than `:one_for_one` (which is rare), you can simply hoist Eternal to a tree above your main application tree. This is a little more complicated, but ensures your tables are safe. You can do this using something like the following (you can see how Eternal is distanced from your app logic which may cause a restart):\n\n```elixir\ndefmodule MyApplication do\n  # define application\n  use Application\n\n  # See http://elixir-lang.org/docs/stable/elixir/Application.html\n  # for more information on OTP Applications\n  def start(_type, _args) do\n    import Supervisor.Spec, warn: false\n\n    # Note how we create our main application tree separately to our Eternal\n    # tree, thus making Eternal resistant to crashes around your application.\n    children = [\n      supervisor(Eternal, [:table, [ :compressed ], [ quiet: true ]]),\n      supervisor(Supervisor, [MyApplication.OneForAllSupervisor, [ ]])\n    ]\n\n    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html\n    # for other strategies and supported options\n    opts = [ strategy: :one_for_one ]\n    Supervisor.start_link(children, opts)\n  end\nend\n\ndefmodule MyApplication.OneForAllSupervisor do\n  use Supervisor\n\n  def init([]) do\n    children = [ worker(MyModuleWhichMightCrash, []) ]\n    supervise(children, strategy: :one_for_all)\n  end\nend\n```\n\n## Contributions\n\nIf you feel something can be improved, or have any questions about certain behaviours or pieces of implementation, please feel free to file an issue. Proposed changes should be taken to issues before any PRs to avoid wasting time on code which might not be merged upstream.\n\n## Credits\n\nThanks to the following for the inspiration for this project:\n\n- [Daniel Berkompas](https://github.com/danielberkompas/immortal)\n- [Steve Vinoski](http://steve.vinoski.net/blog/2011/03/23/dont-lose-your-ets-tables/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitfin%2Feternal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwhitfin%2Feternal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitfin%2Feternal/lists"}