I have a number of websites in phoenix and a “master” one. I want to be able to switch all of the websites to maintance mode via REST API by sending a certain request from the master one. And not by manually creating a “maintenance.html” file in an nginx directory, for each website one by one by logging in into it via ssh. But via REST API. As a result any url requested in a website would be handled by
get("/*path", PageController, :maintenance_mode)
by Phoenix, not nginx, and which, the route, otherwise would be inactive.
And I want to be able to switch it on and off.
Therefore, there would have to be a condition in router.ex, right?
In the normal mode this would be active:
get("/*path", ErrorController, :not_found)
How would I implement it?
If you want this to work for all routes then I would implement this by adding a plug to the endpoint. Inside the plug you’d check if the site is in maintenance mode (via an in-memory store or database value). If so then render the maintenance page and halt the Plug.Conn.
How do I add such a plug? One that would render a maintanance page or text “maintanance” and also halt all other routes and requests, by a condition? Note that in defmodule MyAppWeb.Router do
I have multiple pipelines and scopes.
Put in your MyAppWeb.Endpoint
, as high as you need to:
plug MyAppWeb.Maintenance
And then create module
defmodule MyAppWeb.Maintenance do
@behaviour Plug
def begin, do: :persistent_term.put(__MODULE__, true)
def finish, do: :persistent_term.erase(__MODULE__)
@impl true
def init(_), do: []
@impl true
def call(conn, _opts) do
case :persistent_term.get(__MODULE__, false) do
false -> conn
true -> conn |> Plug.Conn.send_resp(503, "Maintenance") |> Plug.Conn.halt()
end
end
end
Now you can start your maintenance by calling MyAppWeb.Maintenance.begin()
and end it via MyAppWeb.Maintenance.finish()
.
13 Likes