defmodule MessageServer.RemoteClient do require Logger alias MessageServer.{MessageRequest, ServerRegistry, Auth, MessageQueue} @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}") MessageQueue.queue_message(target_server_id, payload) 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