Make Odoo GenServer more resilient
i.e. do not crash if Odoo is not available or configuration not set
This commit is contained in:
parent
785e096f4b
commit
1133025016
1 changed files with 110 additions and 0 deletions
110
lib/recycledcloud/odoo.ex
Normal file
110
lib/recycledcloud/odoo.ex
Normal file
|
@ -0,0 +1,110 @@
|
|||
defmodule RecycledCloud.Odoo do
|
||||
use GenServer
|
||||
require Logger
|
||||
|
||||
@common_endpoint "/xmlrpc/2/common"
|
||||
@object_endpoint "/xmlrpc/2/object"
|
||||
|
||||
# Odoo 14.0 API is documented at https://www.odoo.com/documentation/14.0/webservices/odoo.html
|
||||
|
||||
defp get_odoo_config(key) do
|
||||
Application.get_env(:recycledcloud, :odoo, []) |> Keyword.get(key)
|
||||
end
|
||||
|
||||
defp post!(call, endpoint) do
|
||||
url = get_odoo_config(:server) <> endpoint
|
||||
opts = [proxy_auth: {get_odoo_config(:user), get_odoo_config(:secret)}]
|
||||
headers = []
|
||||
body = call |> XMLRPC.encode!
|
||||
|
||||
response = HTTPoison.post!(url, body, headers, opts).body |> XMLRPC.decode!
|
||||
case response do
|
||||
%{fault_code: _, fault_string: err} -> {:error, err}
|
||||
%{param: result} -> {:ok, result}
|
||||
end
|
||||
end
|
||||
|
||||
defp authenticate do
|
||||
auth_params = [
|
||||
get_odoo_config(:database),
|
||||
get_odoo_config(:user),
|
||||
get_odoo_config(:secret),
|
||||
nil
|
||||
]
|
||||
|
||||
auth_response = %XMLRPC.MethodCall{method_name: "authenticate", params: auth_params}
|
||||
|> post!(@common_endpoint)
|
||||
case auth_response do
|
||||
{:ok, false} -> {:error, "Could not authenticate against Odoo."}
|
||||
{:ok, uid} -> {:ok, uid}
|
||||
{:error, err} -> {:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_odoo_config(key) do
|
||||
case get_odoo_config(key) do
|
||||
nil ->
|
||||
Logger.warn("Odoo #{key} configuration is missing.")
|
||||
false
|
||||
_value -> true
|
||||
end
|
||||
end
|
||||
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
|
||||
end
|
||||
|
||||
def init(:ok) do
|
||||
# Make sure Odoo configuration is defined.
|
||||
conf_ok? = for key <- [:server, :database, :user, :secret], reduce: true do
|
||||
acc -> acc && check_odoo_config(key)
|
||||
end
|
||||
|
||||
if conf_ok? do
|
||||
case authenticate() do
|
||||
{:ok, uid} ->
|
||||
# Print Odoo version on console (not quite useful...).
|
||||
version_call = %XMLRPC.MethodCall{method_name: "version", params: []} |> post!(@common_endpoint)
|
||||
{:ok, %{"server_version" => version}} = version_call
|
||||
Logger.info("Successfuly authenticated against Odoo #{version} at #{get_odoo_config(:server)}")
|
||||
|
||||
{:ok, uid}
|
||||
{:error, err} ->
|
||||
Logger.warning("Failed to authenticate against Odoo: #{inspect(err)}")
|
||||
|
||||
# We do not fail here since we do not want to hinder the application's
|
||||
# main supervisor if Odoo is down.
|
||||
{:ok, nil}
|
||||
end
|
||||
else
|
||||
Logger.warning("Failed to authenticate against Odoo: missing configuration!")
|
||||
|
||||
{:ok, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call({method, params}, _from, uid) do
|
||||
case uid do
|
||||
# uid is nil if start_link's init/1 call failed.
|
||||
# ... we try to authenticate once again!
|
||||
nil ->
|
||||
case init(:ok) do
|
||||
{:ok, new_uid} -> handle_call({method, params}, nil, new_uid)
|
||||
err -> {:reply, err, nil}
|
||||
end
|
||||
_ ->
|
||||
call = %XMLRPC.MethodCall{
|
||||
method_name: method,
|
||||
params: [get_odoo_config(:database), uid, get_odoo_config(:secret) | params]
|
||||
}
|
||||
result = call |> post!(@object_endpoint)
|
||||
|
||||
{:reply, result, uid}
|
||||
end
|
||||
end
|
||||
|
||||
def query(params), do: execute_kw(params)
|
||||
defp execute_kw(params) do
|
||||
GenServer.call(__MODULE__, {"execute_kw", params})
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue