Git Product home page Git Product logo

eternal's Introduction

Eternal

Build Status Coverage Status Hex.pm Version Documentation

Eternal 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.

Installation

Eternal is available on Hex. You can install the package via:

  1. Add eternal to your list of dependencies in mix.exs:

    def deps do
      [{:eternal, "~> 1.3"}]
    end
  2. Ensure eternal is started before your application:

    def application do
      [applications: [:eternal]]
    end

Usage

Manual Startup

The 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 start_link/3 which behaves quite similarly to :ets.new/2. The 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.

iex> Eternal.start_link(:table1, [ :set, { :read_concurrency, true }])
{ :ok, #PID<0.402.0> }
iex> Eternal.start_link(:table2, [ :set, { :read_concurrency, true }], [ quiet: true ])
{ :ok, #PID<0.406.0> }

For further usage examples, please see the documentation.

Application Supervision

I'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.

defmodule MyApplication do
  # define application
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    # Define workers and child supervisors to be supervised
    children = [
      supervisor(Eternal, [:table, [ :compressed ], [ quiet: true ]])
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [ strategy: :one_for_one ]
    Supervisor.start_link(children, opts)
  end
end

If 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):

defmodule MyApplication do
  # define application
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    # Note how we create our main application tree separately to our Eternal
    # tree, thus making Eternal resistant to crashes around your application.
    children = [
      supervisor(Eternal, [:table, [ :compressed ], [ quiet: true ]]),
      supervisor(Supervisor, [MyApplication.OneForAllSupervisor, [ ]])
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [ strategy: :one_for_one ]
    Supervisor.start_link(children, opts)
  end
end

defmodule MyApplication.OneForAllSupervisor do
  use Supervisor

  def init([]) do
    children = [ worker(MyModuleWhichMightCrash, []) ]
    supervise(children, strategy: :one_for_all)
  end
end

Application callback

If your application would like to be informed when the supervisor is operation and the :ets table is created you may pass the option :callback to the Eternal.start_link/3 and Eternal.start/3 functions. The callback is a function specification of the form either {Module, function, [args]} or a function capture. For example:

# The parameters pid and table are passed to the callback
iex> Eternal.start_link MyTable, [], callback: fn pid, table -> callback_fun(pid, table) end

# The parameters pid and table are pre-prended to args
iex> Eternal.start_link Eternal, [], callback: {MyModule, :callback_fun, []}, quiet: true

Contributions

If 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.

Credits

Thanks to the following for the inspiration for this project:

eternal's People

Contributors

kipcole9 avatar whitfin avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.