File size: 1,970 Bytes
936b397 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | defmodule Plausible.InstallationSupport.Check do
@moduledoc """
Behaviour to be implemented by a specific installation support check.
`report_progress_as()` doesn't necessarily reflect the actual check
description, it serves as a user-facing message grouping mechanism,
to prevent frequent message flashing when checks rotate often.
Each check operates on `%Plausible.InstallationSupport.State{}` and is
expected to return it, optionally modified, by all means. `perform_safe/1`
is used to guarantee no exceptions are thrown by faulty implementations,
not to interrupt LiveView.
"""
@type state() :: Plausible.InstallationSupport.State.t()
@callback report_progress_as() :: String.t()
@callback perform(state(), Keyword.t()) :: state()
defmacro __using__(_) do
quote do
import Plausible.InstallationSupport.State
alias Plausible.InstallationSupport.State
require Logger
@behaviour Plausible.InstallationSupport.Check
def perform_safe(state, opts) do
timeout = Keyword.get(opts, :timeout, 10_000)
task =
Task.async(fn ->
try do
perform(state, opts)
catch
_, e ->
Logger.error(
"Error running check #{inspect(__MODULE__)} on #{state.url}: #{inspect(e)}"
)
put_diagnostics(state, service_error: %{code: :internal_check_error, extra: e})
end
end)
try do
Task.await(task, timeout)
catch
:exit, {:timeout, _} ->
Task.shutdown(task, :brutal_kill)
check_name = __MODULE__ |> Atom.to_string() |> String.split(".") |> List.last()
put_diagnostics(state,
service_error: %{
code: :internal_check_timeout,
extra: "#{check_name} timed out after #{timeout}ms"
}
)
end
end
end
end
end
|