Skip to content
Дамјан Георгиевски edited this page May 2, 2020 · 3 revisions

ircbot State Machine

Here I try to document the finite state machine I've created for the bot.

The core of the bot is a gen_statem process that has two child processes. First of the children is a gen_event process that manages the Plugins. The other process is created when needed and handles the tcp connection. The state machine (ircbot_statem.erl) has 4 states: standby, connecting, registering, ready, and reconnect.

standby

The bot starts in the standby state and it only cares about one event, the connect command. When it receives the connect command, it'll spawn a connection process and change to the connecting state. It will also set a timeout (CONNECT_TIMEOUT), so that if no events happen in that time, a timeout event is sent.

connecting

In the connecting state we handle 3 events: timeout, exit and success. success is sent from the connection process when the TCP connection is successfully established, the bot then sends the irc login commands and changes to the registering state (again with a timeout set, REGISTER_TIMEOUT).

The exit event is triggered when the fsm detects that the connection child process is dead (see also handle_info in the fsm source). timeout is triggered if no other event is received for CONNECT_TIMEOUT time (this needs to be at least as long as a dns resolve could take). Both on exit and timeout the handler will send a reconnect event to itself and change back to the standby state.

registering

The registering state is very similar to the connecting. It similarly handles a timeout and exit events and goes back to the standby state.

The main purpose of this state is to wait for the 001 "welcome" response from the irc server. When it receives it, it'll notify the plugins that the system is online, and continue to the ready state. Then it's the job of plugins, like for example the channels plugin will connect to all the configured channels, to initialize their state.

Here I should probably also handle a 433 "nickname is in use" response from the irc server.

ready

The ready state is the main operational state of the ircbot. It handles a {send, Msg} and {received, Msg} events (commands). The {send, Msg} command is forwarded to the connection process. The {received, Msg} event is received from the connection process, and dispatched to the gen_event manager that handles the plugins. Everything else is handled by the plugins (including joining channels, responding to server PINGs and to CTCP requests).

The ready state doesn't have any timeouts, but the connection process will die if there's nohing happening for some time. In the ready state I handle the exit event, which as ever will change to standby and trigger a reconnect event.

reconnect

Other handlers

There is a global synchronous handler for the disconnect command. And also for plugin management, the commands add_plugin, delete_plugin and which_plugins are mapped on the ircbot_plugins/gen_event functions.

notes

There are some catch-all event handlers in almost all the states that should probably be removed. It's a kind of defensive programing that's not idiomatic in the Erlang world. The Erlang way is "fail early, fail often… and use supervisors!".

Clone this wiki locally