Add a buffer for slowing message output to avoid flooding out the bot
This commit is contained in:
parent
38d3ae44b4
commit
6e8e3172c9
1 changed files with 79 additions and 0 deletions
79
lib/nulform/buffer.ex
Normal file
79
lib/nulform/buffer.ex
Normal 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
|
Loading…
Reference in a new issue