Skip to main content

Project 02/03MC-SYS-01

All projects

AREA

Action–reaction automation across six third-party services, dispatched through two RabbitMQ queues.

Year
2024
Stack
  • Golang
  • Gin
  • RabbitMQ
  • MariaDB
  • React
  • TypeScript
  • Docker
  • GitHub

01Problem

Let a user link services together: when an action occurs in one service (for example a commit on GitHub), one or more reactions run in others. At filing, the integrated services are Microsoft, Google, GitHub, Spotify, Twitch and Discord.

The user builds and manages these workflows from a React web interface.

Modelled on IFTTT. Source code is public on GitHub under ASM-Studios.

Fig. 2.2 — Workflow editor: name, then action ("When"), then reactions ("Then").

02Architecture

Data paths, in order

Fig. 1.1 — AREA: workflow path from the front end through the action and reaction queues.

The front end sends workflow definitions to the main program, a Go server built on Gin. The server publishes each workflow to an action queue; several action consumers read from it. When an action is detected, the workflow moves on to a reaction queue, where reaction consumers execute it. Both queues run on RabbitMQ. MariaDB holds users, services and workflows.

Redrawn from the project diagram. Consumer counts (two action, three reaction) are as drawn there, not a deployment figure.

Decision 01 / 07

Server written in Go, on Gin

Decision
The server is written in Go with the Gin framework; dependencies are pinned with Go Modules.
Rationale
Go compiles to native code, with fast execution and low resource usage; goroutines and channels give it a strong concurrency model; its syntax is minimal and pulls in few dependencies. Against NestJS and Flask, the comparison on file rates Go highest on performance and scalability. Code factorisation and middleware simplify route management.
Trade-off
The same comparison rates Go's learning curve as moderate and its ecosystem as less mature than NestJS or Flask.

Decision 02 / 07

Queues between the server and the workers

Decision
Split the back end into services — main program, action consumers, reaction consumers — that communicate only through RabbitMQ, instead of a single monolith.
Rationale
Stated aims: scalability and fault tolerance. Each stage is a separate consumer of its own queue, so stages are added or restarted independently of the server.
Fig. 2.3 — Monolith against the microservice split adopted.
Fig. 2.4 — Source diagram for Fig. 1.1.

Decision 03 / 07

One relational schema, three table groups

Decision
Store everything in MariaDB, with tables grouped by domain: users (red), services (blue), workflows (green).
Rationale
Stated aim: consistency and integrity of the data. Workflows join users to service events and parameters, which the schema expresses as foreign keys.
Fig. 2.5 — MariaDB schema. Red: users · Blue: services · Green: workflows.

Decision 04 / 07

Variables carried from action to reaction

Decision
An action declares variables — for a GitHub commit: author name, author email, date, message — which the action consumer passes to the reaction consumer as arguments. Reactions can be chained.
Rationale
Reactions can be configured from the data of their trigger, which allows multi-step workflows instead of fixed one-to-one links.
Fig. 2.6 — Arguments passed from the action consumer to the reaction consumer.

Decision 05 / 07

A fixed procedure for adding services

Decision
Each service is declared as data — its events, their type (action or reaction), variables and parameters — and each trigger is registered as one handler in a map keyed by event id.
Rationale
Designed for extension: a new service, action or reaction is a declaration plus a handler, in a few steps.
Fig. 2.7 — Service declaration: events, variables, parameters.
Fig. 2.8 — Trigger registry: one handler per event id.

Decision 06 / 07

Authentication: OAuth2 and TOTP

Decision
Users authenticate through OAuth2; TOTP (time-based one-time passwords) adds a second factor.
Rationale
Stated aim: protect user data and account security.

Decision 07 / 07

Containers and CI/CD

Decision
Every component ships as a Docker container; a GitHub pipeline automates tests and deployment.
Rationale
The same images run in development, testing and production.

03Result

No load test is on file. The record holds the qualitative comparison used to choose the server language (below).

The comparison is an assessment, not a benchmark: it contains no measured values.

Fig. 2.9 — Server language assessment: Go against NestJS and Flask.