Packages
Wideact is an inter-lingual actor system, enabling different languages to communicate seamlessly over the network. It implements a very primitive protocol, capable of only transmiting messages to named actors. It also serves with semi-persistence, and will save messages for an actor until they ar...
Current section
Files
Jump to
Current section
Files
lib/stalemail.ex
defmodule StaleMail do
@moduledoc """
Stalemail is a persistent mailbox system used by Wideact.
"""
@doc """
Starts up the mailbox loop.
"""
def start() do
loop(%{})
end
@doc """
Loops through the received messages, parsing them and updating the mailbox state.
"""
defp loop(state) do
newstate = receive do
x -> parse(state, x)
end
loop(newstate)
end
@doc """
Parses the new message for updating the state.
The :new_mailbox message connects a new client and creates a new mailbox if one is not already present. :new_mail is a check for new mail, which sends back the first of received messages for a given user. The :got_mail message is an acknowledgement that the user has received the first message, and it can be removed from the mailbox.
The :pass_message message is the basic transfer mechanism in stalemail, passing the message to the receiver's mailbox (creating one in the process if not there).
"""
def parse(state, arg) do
case arg do
{ :new_mailbox, zname, _sender } ->
name = String.strip(zname)
old = Map.has_key?(state, name)
newstate = unless old do
Map.put(state, name, [])
else
state
end
newstate
{ :new_mail, zname, sender } ->
name = String.strip(zname)
# TODO: asking about new mail
if state |> Map.has_key?(name) do
case state |> Map.get(name, []) do
[ head | _tail ] ->
send sender, head
state
_ -> state
end
end
state
{ :got_mail, zname } ->
name = String.strip(zname)
# TODO: delete mail with given key
if state |> Map.has_key?(name) do
case state |> Map.get(name, []) do
[ _ | tail ] ->
state |> Map.put(name, tail)
_ -> state
end
else
state
end
{ :pass_message, zreceiver, zmessage, zsender } ->
receiver = String.strip(zreceiver)
message = String.strip(zmessage)
sender = String.strip(zsender)
# TODO: passes message to mailbox of receiver
if Map.has_key?(state, receiver) do
list = state |> Map.get(receiver, [])
state |> Map.put(receiver, list ++ [ { :received_message, sender, message } ])
else
state |> Map.put(receiver, [ { :received_message, sender, message } ])
end
end
end
end