Add a buffer for slowing message output to avoid flooding out the bot

This commit is contained in:
Mikko Ahlroth 2013-07-07 13:43:36 +03:00
parent 38d3ae44b4
commit 6e8e3172c9

79
lib/nulform/buffer.ex Normal file
View file

@ -0,0 +1,79 @@
defmodule Nulform.Buffer do
use GenServer.Behaviour
@moduledoc """
A buffer takes outgoing messages from the bot and sends them to the
given connection process with a delay to prevent the bot from flooding
itself out of the network.
The algorithm is as follows (reasonable values are t = 2, m = 10):
1. Read messages from input
2. Insert messages into queue
3. Set timer to be current time, if lower
4. For each message
4.1. Raise timer value by t
4.2. If timer value is higher than current time + m, next send is
at current time + t, otherwise send message immediately
"""
defrecord Data,
connection: nil,
buffer: [] :: list,
waiting: :false,
timer: 0 :: integer
def init(pid) do
data = Data.new(connection: pid)
{:ok, data}
end
def handle_cast(msg, data) do
data = data.buffer data.buffer ++ [msg]
data = handle_buffer data
{:noreply, data}
end
def handle_info(msg, data) do
case msg do
{:send_message} ->
data = send_message data
data = handle_buffer data
end
{:noreply, data}
end
defp handle_buffer(data) do
{_, time, _} = :erlang.now()
if data.timer < time do
data = data.timer time
end
if (data.timer - time) <= 10 do
if not Enum.empty? data.buffer do
data = send_message data
data = data.waiting :false
end
else
if (not Enum.empty? data.buffer) and not data.waiting do
{:ok, timer} = :timer.send_after 2000, {:send_message}
data = data.waiting :true
end
end
data
end
defp send_message(data) do
data = data.waiting :false
if not Enum.empty? data.buffer do
[msg | tail] = data.buffer
data = data.buffer tail
data.connection <- {:nulform, :msg_out, msg}
data = data.timer data.timer + 2
else
data
end
end
end