I am currently going through Elixir in Action and i am doing some refactoring of my Todo
application code to get a better grasp on the main parts of OTP.
The application uses a database that simply stores data in files on the disk. To ensure that the target folder for the database exists, File.mkdir_p!(db_folder)
is called inside the database process. The database process itself uses a bunch of worker processes to perform the actual storing/retrieving of data from disk.
The chapter i am currently at introduces a DIY process registry to implement a more robust supervision tree, by having the workers register themselves to the registry and having the database process lookup the worker using the registry, so both parties can be supervised and will still work after a failure.
When Elixir 1.4 came out i read about the Registry
module in the patch notes, so i thought i might refactor the app and use that. Now it turns out, that the database process does not really have to know about the folder the database uses for storing data. So i took the mkdir_p!
call out of that module and thought about where to put it. Two options come to mind:
- The
DatabaseWorker
- The
DatabaseWorkerSupervisor
I personally prefer the second approach, since the whole app is bound to crash anyways if the user has no access rights to the persistence folder. But I am not quite sure if it is okay to put logic into a Supervisor.
Is putting logic into a Supervisor bad style or acceptable depending on the situation? If it is bad style, where do i put startup-logic that i do not want to be repeated if a process crashes?
My Supervisor code:
defmodule Todo.DatabaseWorkerSupervisor do
use Supervisor
def start_link(db_folder) do
Supervisor.start_link(__MODULE__, db_folder)
end
def init(db_folder) do
File.mkdir_p!(db_folder)
processes =
for worker_id <- 1..3 do
worker(Todo.DatabaseWorker, [db_folder, worker_id], id: {:dbworker, worker_id})
end
supervise(processes, strategy: :one_for_one)
end
end