From 2966723ab41422f16077558896370245a336352c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 Mar 2020 19:49:55 +0100 Subject: [PATCH] doc: add basic architecture document --- doc/architecture.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 doc/architecture.md diff --git a/doc/architecture.md b/doc/architecture.md new file mode 100644 index 0000000..3484185 --- /dev/null +++ b/doc/architecture.md @@ -0,0 +1,37 @@ +# soju architecture + +soju manages two types of connections: + +- Upstream connections: soju maintains persistent connections to + user-configured IRC servers +- Downstream connections: soju accepts connections from IRC clients + +On startup, soju will iterate over the list of networks stored in the database +and try to open an upstream connection for each network. + +## Ring buffer + +In order to correctly send history to each downstream client, soju maintains +for each network a single-producer multiple-consumer ring buffer. The network's +upstream connection produces messages and multiple downstream connections +consume these messages. Each downstream client may have a different cursor in +the history: for instance a client may be 10 messages late while another has +consumed all pending messages. + +## Goroutines + +Each type of connection has two dedicated goroutines: the first one reads +incoming messages, the second one writes outgoing messages. + +Each user has a dedicated goroutine responsible for dispatching all messages. +It communicates via channels with the per-connection reader and writer +goroutines. This allows to keep the dispatching logic simple (by avoiding any +race condition or inconsistent state) and to rate-limit each user. + +The user dispatcher goroutine receives from the `user.events` channel. Upstream +and downstream message handlers are called from this goroutine, thus they can +safely access both upstream and downstream state. + +In addition to these goroutines, each downstream connection also has one +goroutine per network to handle new upstream messages coming from the ring +buffer.