Background Job Processing using GenServer / GenStage?

A GenServer-implementing approach would be something like the following:

defmodule BackgroundWorker do
  use GenServer

  def start_link() do
    {:ok, pid} = GenServer.start_link(__MODULE__, nil)
    pid
  end

  # Outward-facing API
  def add_job(pid, job_function) do
    # async message passing.
    GenServer.cast(pid, {:add_job, job_function})
  end

  # Internal Callback
  def handle_cast({:add_job, job_function}, _state) when is_function(job_function) do
    # The BackgroundWorker GenServer uses the message mailbox as queue.
    function.()
    {:noreply, nil}
  end
end

This simple implementation (note: untested, maybe there are typos) handles exactly one job at a time, but can of course be extended to handle multiple ones by adding another layer of indirection.