Dispatcher
Routes incoming Telegram updates to appropriate handlers. Configurable max goroutines (default: 200) with enhanced error handling and panic recovery.
Alita Robot is a modern Telegram group management bot built with Go and the gotgbot library. This document provides an overview of the architectural decisions, technology stack, and design principles that guide the codebase.
| Component | Technology | Purpose |
|---|---|---|
| Language | Go 1.25+ | Core application runtime |
| Telegram Library | gotgbot v2 | Telegram Bot API wrapper |
| Build System | GoReleaser | Multi-platform builds and releases |
| Component | Technology | Purpose |
|---|---|---|
| Database | PostgreSQL | Persistent data storage |
| ORM | GORM | Object-relational mapping |
| Migrations | Custom Engine | Schema versioning with transactional execution |
The database uses a surrogate key pattern: auto-increment id as PK with external IDs (user_id, chat_id) as unique constraints.
| Component | Technology | Purpose |
|---|---|---|
| Caching | Redis | Distributed caching layer |
| Client | gocache | Go cache library with marshaling |
| Stampede Protection | singleflight | Prevents thundering herd on cache misses |
All cache keys are prefixed with alita: for namespace isolation. TTLs range from 20 seconds (anonymous admin verification) to 1 hour (language preferences).
| Component | Technology | Purpose |
|---|---|---|
| Metrics | Prometheus | Metrics and observability |
| Tracing | OpenTelemetry | Distributed tracing with OTLP/console exporters |
| Health | HTTP /health | Unified health, metrics, pprof on single port |
Dispatcher
Routes incoming Telegram updates to appropriate handlers. Configurable max goroutines (default: 200) with enhanced error handling and panic recovery.
Module System
Feature modules in alita/modules/ follow a consistent pattern: moduleStruct, handler methods, LoadModule registration. Help module loads last to collect all commands.
Cache Layer
Redis caching with singleflight stampede protection. Per-type TTLs, automatic invalidation on writes, and traced operations via OpenTelemetry.
Permission System
Centralized permission validation in alita/utils/chat_status/. Checks are cached to reduce Telegram API calls. Supports anonymous admin detection.
Monitoring
4-tier auto-remediation, activity tracking (per-chat and per-user DAU/WAU/MAU), background stats every 30s, and GC triggers on memory thresholds.
Graceful Shutdown
Central coordinator with LIFO handler execution. Each handler gets panic recovery. Total timeout: 60 seconds.
All database operations are organized by domain in alita/db/*_db.go files. Each file provides Get/Add/Update/Delete functions for its domain, with surrogate key pattern (auto-increment id as PK, external IDs as unique constraints):
// Example: Direct domain function callssettings := db.GetChatSettings(chatId)db.UpdateChatSettings(chatId, newSettings)Middleware functionality is implemented through decorators in alita/utils/decorators/. Common cross-cutting concerns are handled uniformly:
Concurrent processing uses bounded worker pools with panic recovery:
DISPATCHER_MAX_ROUTINES)Redis-based caching with stampede protection:
+------------------+ | Telegram | | Bot API | +--------+---------+ | +------------------+------------------+ | | Webhook Mode Polling Mode | | v v +----------+----------+ +-----------+-----------+ | HTTP Server | | Updater | | /webhook/{secret} | | GetUpdates loop | +----------+----------+ +-----------+-----------+ | | +------------------+------------------+ | v +----------+----------+ | Dispatcher | | (configurable routines)| +----------+----------+ | +-------------------+-------------------+ | | | v v v +------+------+ +------+------+ +------+------+ | Handler | | Handler | | Handler | | (Command) | | (Callback) | | (Message) | +------+------+ +------+------+ +------+------+ | | | +-------------------+-------------------+ | +--------------+--------------+ | | v v +---------+----------+ +---------+----------+ | Redis Cache | | PostgreSQL | | (cache lookup) | | (via GORM) | +--------------------+ +--------------------+The dispatcher routes incoming Telegram updates to appropriate handlers:
dispatcher := ext.NewDispatcher(&ext.DispatcherOpts{ Error: func(b *gotgbot.Bot, ctx *ext.Context, err error) ext.DispatcherAction { // Error handling with structured logging return ext.DispatcherActionNoop }, MaxRoutines: config.AppConfig.DispatcherMaxRoutines,})Each feature module follows a consistent pattern:
moduleStruct with module nameLoadModule functionalita/main.go in specific orderRedis caching with stampede protection:
alita: for namespace isolationComprehensive monitoring subsystems:
// Dispatcher limits concurrent handler executionMaxRoutines: 200 // Configurable via DISPATCHER_MAX_ROUTINES
// Worker pools use bounded parallelismworkerPool := NewWorkerPool(config.AppConfig.WorkerPoolSize)// Prevents multiple goroutines from rebuilding same cache entryvar cacheGroup singleflight.Group
result, err, _ := cacheGroup.Do(cacheKey, func() (any, error) { // Only one goroutine executes this return loadFromDatabase()})// Shutdown manager coordinates cleanup in ordershutdownManager := shutdown.NewManager()shutdownManager.RegisterHandler(func() error { // Cleanup monitoring, database, cache return nil})Alita uses a 4-layer error handling hierarchy:
Error: func(b *gotgbot.Bot, ctx *ext.Context, err error) ext.DispatcherAction { defer error_handling.RecoverFromPanic("DispatcherErrorHandler", "Main") // Log error with structured fields return ext.DispatcherActionNoop}Worker pools implement panic recovery:
go func() { defer func() { if r := recover(); r != nil { log.WithField("panic", r).Error("Panic in worker") } }() // Worker logic}()Individual handlers use decorators for error handling:
// Permission checks return early on failureif !chat_status.RequireUserAdmin(b, ctx, nil, user.Id, false) { return ext.EndGroups}Command decorators provide permission validation and error context:
// Decorators wrap handlers with cross-cutting concernscmdDecorator.MultiCommand(dispatcher, []string{"cmd", "alias"}, handler)The database uses a surrogate key pattern:
id field (internal identifier)user_id and chat_id with unique constraints