message-server/lib/message_server/message_handler.ex

69 lines
2.2 KiB
Elixir

defmodule MessageServer.MessageHandler do
require Logger
alias MessageServer.{
MessageRequest,
RemoteClient,
ServerRegistry,
Storage
}
@spec handle_message(MessageRequest.t()) :: :ok | {:error, String.t()}
def handle_message(%MessageRequest{from: from, to: to, message: message}) do
with {:ok, from_server} <- extract_server_id(from),
{:ok, to_server} <- extract_server_id(to),
:ok <- validate_sender_ownership(from_server),
:ok <- route_message(to_server, from, to, message) do
Logger.info("Message routed successfully from #{from} to #{to}")
:ok
else
{:error, reason} = error ->
Logger.warning("Message routing failed: #{reason}")
error
end
end
@spec extract_server_id(String.t()) :: {:ok, String.t()} | {:error, String.t()}
defp extract_server_id(user_id) do
case String.split(user_id, "-", parts: 2) do
[server_id, _user_part] -> {:ok, server_id}
_ -> {:error, "Invalid user ID format: #{user_id}"}
end
end
@spec validate_sender_ownership(String.t()) :: :ok | {:error, String.t()}
defp validate_sender_ownership(sender_server) do
local_server = ServerRegistry.get_server_id()
if sender_server == local_server do
:ok
else
{:error, "Cannot send messages on behalf of users from other servers"}
end
end
@spec route_message(String.t(), String.t(), String.t(), String.t()) ::
:ok | {:error, String.t()}
defp route_message(to_server, from, to, message) do
local_server = ServerRegistry.get_server_id()
if to_server == local_server do
handle_local_message(from, to, message)
else
handle_remote_message(to_server, from, to, message)
end
end
@spec handle_local_message(String.t(), String.t(), String.t()) :: :ok | {:error, String.t()}
defp handle_local_message(from, to, message) do
Storage.append_message(to, from, message)
end
@spec handle_remote_message(String.t(), String.t(), String.t(), String.t()) ::
:ok | {:error, String.t()}
defp handle_remote_message(to_server, from, to, message) do
payload = %MessageRequest{from: from, to: to, message: message}
RemoteClient.send_message_to_server(to_server, payload)
end
end