65 lines
2.2 KiB
Elixir
65 lines
2.2 KiB
Elixir
defmodule MessageServer.RemoteClient do
|
|
require Logger
|
|
|
|
alias MessageServer.{MessageRequest, ServerRegistry, Auth}
|
|
|
|
@spec send_message_to_server(String.t(), MessageRequest.t()) :: :ok | {:error, String.t()}
|
|
def send_message_to_server(target_server_id, payload) do
|
|
with {:ok, server_info} <- ServerRegistry.get_server_info(target_server_id),
|
|
{:ok, serialized_payload} <- serialize_payload(payload),
|
|
{:ok, response} <- make_request(server_info, serialized_payload) do
|
|
handle_response(response)
|
|
else
|
|
{:error, :not_found} ->
|
|
{:error, "Unknown server: #{target_server_id}"}
|
|
|
|
{:error, reason} = error ->
|
|
Logger.error("Failed to send message to server #{target_server_id}: #{reason}")
|
|
error
|
|
end
|
|
end
|
|
|
|
@spec serialize_payload(MessageRequest.t()) :: {:ok, binary()} | {:error, String.t()}
|
|
defp serialize_payload(payload) do
|
|
try do
|
|
serialized = :erlang.term_to_binary(payload)
|
|
{:ok, serialized}
|
|
rescue
|
|
error -> {:error, "Serialization failed: #{inspect(error)}"}
|
|
end
|
|
end
|
|
|
|
@spec make_request(map(), binary()) :: {:ok, Req.Response.t()} | {:error, String.t()}
|
|
defp make_request(%{host: host, port: port}, serialized_payload) do
|
|
url = "http://#{host}:#{port}/api/remote/messages"
|
|
local_server_id = ServerRegistry.get_server_id()
|
|
auth_token = Auth.generate_auth_token(local_server_id)
|
|
|
|
case Req.post(url,
|
|
body: serialized_payload,
|
|
headers: [
|
|
{"content-type", "application/octet-stream"},
|
|
{"authorization", "Bearer #{auth_token}"}
|
|
]
|
|
) do
|
|
{:ok, %Req.Response{status: status} = response} when status in 200..299 ->
|
|
{:ok, response}
|
|
|
|
{:ok, %Req.Response{status: status}} ->
|
|
{:error, "HTTP #{status}"}
|
|
|
|
{:error, reason} ->
|
|
{:error, "Request failed: #{inspect(reason)}"}
|
|
end
|
|
end
|
|
|
|
@spec handle_response(Req.Response.t()) :: :ok | {:error, String.t()}
|
|
defp handle_response(%Req.Response{body: body}) do
|
|
case body do
|
|
%{"status" => "success"} -> :ok
|
|
%{"error" => error} -> {:error, error}
|
|
_ -> {:error, "Invalid response format"}
|
|
end
|
|
end
|
|
end
|