Skip to content
Go Hagiwara edited this page Aug 25, 2020 · 23 revisions

This project, go-sarah, is a general-purpose bot framework that enables developers to create and customize their own bot experiences with any chat service. This comes with a unique feature called "stateful command" as well as some basic features such as command and scheduled task. In addition to those features, this provides rich lifecycle management mechanism including live configuration update, customizable alerting mechanism, automated command/task (re-)building, customizable logger and concurrent command/task execution.

This framework is composed of fine-grained components to provide those features. Those components have their own interfaces and default implementations, so developers are free to customize bot behavior by supplying own implementation. See Components for in-detail description.

Migration Guide

For those who are using the older version of go-sarah, take a look at Migrating from v1.x to v2.x and Migrating from v2.x to v3.x to migrate to the newer version.

Table of Contents

Stateful Command

While typical bot implementation is somewhat "stateless" and hence user-bot interaction does not consider previous user state, go-sarah has an idea of "user's conversational context" to support "stateful command." Below examples depict some useful implementations of stateful command.

Input Arguments in a Conversational Manner

One useful way of stateful command is to let a user supply a series of required arguments in a conversational manner. In this way, the user does not have to supply all arguments at once like ".todo Buy milk 2006-01-02 15:04:05." Instead, the user is encouraged to input required arguments one at a time. Take a look at a capture below:

Game Command

The previous example was a user-friendly helper to gather a series of arguments. Another way to use stateful command is a game command like below:

Under the Hood

When an executed command returns sarah.UserContext as part of sarah.CommandResponse, the context information is stored in sarah.UserContextStorage, and the next input from the same user is fed to a function declared by sarah.UserContext. Details should be found at sarah.UserContextStorage. Example codes that use in-memory sarah.UserContextStorage are located at example/plugins/todo and example/plugins/guess.

Pluggable Unit of Executable Jobs

In this project, two kinds of a pluggable unit of executable jobs, "command" and "scheduled task", are supported.

Command

A command is a pluggable job that is executed against user inputs. Any struct can be a command when it satisfies sarah.Command interface. To ease the construction of sarah.Command and to support live configuration update, sarah.CommandPropsBuilder can be used to safely build a non-contradicting set of arguments to (re-)build sarah.Command instance on the fly. See Command and CommandPropsBuilder for details.

Scheduled Task

While a command is a job that is executed against user inputs, a scheduled task is a job that is executed in a scheduled manner. The result can be sent to a pre-defined default destination or to a destination declared by sarah.ScheduledTaskResult. Just like a command, anything can be a scheduled task as long as a struct implements sarah.ScheduledTask interface. Also sarah.ScheduledTaskPropsBuilder is provided to support live configuration update and (re-)create sarah.ScheduledTask instance on the fly. See ScheduledTask and ScheduledTaskPropsBuilder for details.

Live Configuration Update

Live configuration update is go-sarah's signature feature that reflects updated configuration for command and scheduled task on the fly in a thread-safe manner. For proper settings, see Live Configuration Update.

Customizable Alerting Mechanism

Developers may provide zero or more sarah.Alerter implementations to go-sarah so bot's critical state can be notified to an administrator via preferred communication channels. This alerting job is executed in a panic proof manner so even if one or more alerters fail, the next available alerter still runs until there is no more alerter to call. This is recommended to register one or more alerters for better system availability. See Alerter for details.

Customizable Error Supervisor

A lifecycle of sarah.Bot implementation is managed by go-sarah's core. When sarah.Bot encounters a critical situation or when this can no longer handle the error state, the error can be passed to the core via a designated method. This is the core's task to receive the error, judge the severity, notify critical state to administrators via sarah.Alerters and finally stop failing sarah.Bot if required.

Developers can modify how the escalated error should be treated by registering a supervising function. The function returns sarah.SupervisionDirective to tell if the error state should be notified to the administrator and if the failing sarah.Bot should be stopped.

Automated Command/Task (Re-)building

As previously stated, any struct that implements sarah.Command or sarah.ScheduledTask can be a command or scheduled task, accordingly. To ease those implementations, developers may use sarah.CommandPropsBuilder and sarah.ScheduledTaskPropsBuilder. These builders help developers to construct a non-contradicting set of arguments, sarah.CommandProps and sarah.ScheduledTaskProps, to set up sarah.Command and sarah.ScheduledTask on the fly.

These props become powerful when these are used with Config.PluginConfigRoot setting. When this is set and a configuration file under that directory is updated, corresponding command or scheduled task is re-built in a thread-safe manner to apply the latest configuration change. See CommandPropsBuilder, ScheduledTaskPropsBuilder and Live Configuration Update.

Customizable Logger

Golnag's standard logging library, log package, does not provide Logger interface. The absence of common interface and its minimal implementation lead some developers to a search for an alternate logging library or for a better logging architecture. Many logging libraries are introduced, but none is yet considered as De-facto.

This project, instead of choosing one such logging library, has a log.Logger interface and its default implementation that simply wraps standard log library. A developer may use the preferred logging library by wrapping one to satisfy log.Logger interface. See Logger for details.

Concurrent Command/Task Execution

The core of go-sarah, runner, coordinates other components' job executions with its internal worker. By default sarah.Worker's default implementation that supports panic-proof concurrent job execution is used. A command is also executed in this worker so developers do not have to worry about flooding inputs. Use a preferred sarah.Worker implementation to customize worker behavior.