Hi, I have been using ETS a lot in a vehicle tracking app. After noticing the ArgumentError when a parent process of ETS table terminates, the ETS tables creation are now mostly done on the Application init process.
Would you see any risk with this approach other than the encapsulation? I had to change them to :public but it didn’t affect performance. I’m curious if this is a common practice because if you have a cache why not avoid loosing its data while the modules comply to the let it crash.
A common solution to keep ETS tables around is to create a GenServer with no other purpose than to encapsulate the table. You can avoid running code on that server, but still neatly expose module functions to access it. Here’s a very simple example
defmodule Wrapper do
use GenServer
def init(arg) do
:ets.new(:wrapper, [
:set,
:public,
:named_table,
{:read_concurrency, true},
{:write_concurrency, true}
])
{:ok, arg}
end
def start_link(arg) do
GenServer.start_link(__MODULE__, arg, name: __MODULE__)
end
def get(key) do
case :ets.lookup(:wrapper, key) do
[] ->
nil
[{_key, value}] ->
value
end
end
def put(key, value) do
:ets.insert(:wrapper, {key, value})
end
end
The concurrency options should be tweaked to your use case, but the access level has to be :public like you noticed.
Put the GenServer in your application supervision tree and then usage is
Even though it’s been wrapped in a GenServer all the operations run in the calling process, making it fully concurrent (assuming the correct options are set at table creation).
Another common technique is to have a GenServer create the ETS table, set the heir and gives it away to another GenServer that does the work. See GiveAway
All of the above ideas work. I often create ETS or Mnesia tables in supervisors because you can be sure that code will run before anything it starts so it is a good place for it. Or you can start a GenServer that only holds the ETS table, which also means you have a natural place for update code should you need it later
Hi zkessin, supervisors seems interesting in the top ones. Have you seen an ETS crash so that you decided doing it in the supervisor instead of Application init process?