Server architecture

Introduction#

Two servers, one codebase. The Telegram bot talks to people. The FastAPI webhook talks to machines. Scheduler rides alongside for timed work. They share DatabaseService and NotificationService instead of growing their own copies.

Project structure#

The repository organizes code by responsibility:

  • app/main.py: CLI entrypoint and command dispatch
  • app/servers/: FastAPI webhook server, Telegram bot server, and scheduler server
  • app/services/: Notification orchestration, channel implementations, database abstraction, and utilities
  • app/clients/: Database client and external API clients
  • app/runners/: Data ingestion and notification sending workflows
  • app/core/: Configuration, daemon utilities, and shared settings
  • docs/: Deployment, configuration, and operational guides

Core components#

  • Telegram Bot Server: User commands (/start, /help, /stop, /status, /placement_year, /stats, /noticestats, /web) plus admin /userstats, registration, and admin commands via injected services.
  • Webhook Server: FastAPI-based REST server exposing health checks, web push subscription endpoints, notification dispatch, and statistics endpoints.
  • Scheduler Server: Runs automated update jobs (SuperSet + Emails) and official placement scraping on a cron schedule, independent of the Telegram bot.
  • Configuration and Daemon Utilities: Centralized settings, logging, daemon mode, and PID management for process lifecycle.
  • Services and Clients: Notification orchestration, channel implementations (Telegram, Web Push), database abstraction, and MongoDB client.

Architecture overview#

The system is designed as a distributed, decoupled architecture:

  • CLI entrypoint (main.py) launches one of three modes: bot, webhook, or scheduler.
  • Bot server runs continuously in polling mode, responding to user commands and maintaining user sessions.
  • Webhook server exposes REST endpoints for external systems and internal admin tasks.
  • Scheduler server runs periodic jobs independently, fetching data and broadcasting notifications.
  • All servers share a common configuration and logging setup, and rely on dependency injection for services and clients.

Detailed component analysis#

Telegram bot server#

  • Responsibilities:
  • Command routing (/start, /help, /stop, /status, /placement_year, /stats, /noticestats, /web; admin /userstats)
  • User registration and deactivation
  • Admin command delegation
  • Asynchronous polling loop with graceful shutdown
  • Dependency Injection:
  • DatabaseService, NotificationService, AdminTelegramService, PlacementStatsCalculatorService
  • Session and User Management:
  • Adds users on /start, deactivates on /stop, retrieves user status and stats
  • Error Handling:
  • Graceful shutdown, logging, and safe printing in daemon mode

Webhook server (FastAPI)#

  • Responsibilities:
  • Health checks (/, /health)
  • Web push subscription management (/api/push/subscribe, /api/push/unsubscribe, /api/push/vapid-key)
  • Notification dispatch (/api/notify, /api/notify/telegram, /api/notify/web-push)
  • Statistics endpoints (/api/stats, /api/stats/placements, /api/stats/notices, /api/stats/users)
  • External integration webhook (/webhook/update)
  • Middleware and Routing:
  • CORS middleware
  • Dependency injection via app state and Depends
  • Error Handling:
  • HTTP exceptions with descriptive details
  • Validation via Pydantic models

Scheduler server#

  • Responsibilities:
  • Scheduled update jobs (fetch SuperSet + Emails, send notifications)
  • Official placement data scraping
  • Independent operation from the Telegram bot
  • Scheduling:
  • Update cron hour="0,8-23" IST (midnight plus 8 AM through 11 PM)
  • Daily official placement scrape at noon IST
  • Execution:
  • Uses runners and services directly (no service injection)

Daemon mode operation and process management#

  • Daemon Utilities:
  • Double-fork daemonization, PID file management, status checks, and controlled stop
  • Separate logging for scheduler daemon
  • CLI Integration:
  • main.py supports daemon mode for bot and scheduler
  • Reinitializes logging after fork to ensure proper file handles

Inter-Server communication patterns#

  • No direct inter-server calls:
  • Bot server manages user sessions and commands
  • Webhook server exposes REST endpoints for external integrations
  • Scheduler server operates independently and uses runners/services directly
  • Shared infrastructure:
  • All servers use the same configuration and logging setup
  • Database access is centralized via DatabaseService and DBClient

Dependency analysis#

The system follows a layered dependency structure with clear inversion of control via dependency injection:

  • Servers depend on services, which depend on clients
  • Configuration and daemon utilities are shared across servers
  • Runners encapsulate workflows and are reused by both scheduler and CLI

Performance considerations#

  • Asynchronous design:
  • Bot server uses asynchronous polling
  • Scheduler uses AsyncIOScheduler for non-blocking jobs
  • Rate limiting and batching:
  • TelegramService applies rate limiting when broadcasting to users
  • Long messages are split to comply with Telegram limits
  • Efficient data fetching:
  • UpdateRunner pre-fetches existing IDs to minimize API calls
  • Selective enrichment of jobs reduces expensive operations
  • Resource isolation:
  • Separate daemon logs for bot and scheduler reduce contention
  • Scalability:
  • Webhook server can be horizontally scaled behind a load balancer
  • MongoDB can be sharded for high-volume operations

[No sources needed since this section provides general guidance]

Troubleshooting guide#

  • Health checks:
  • Use GET /health on the webhook server to verify service availability
  • Logs:
  • Bot logs: logs/superset_bot.log
  • Scheduler logs: logs/scheduler.log
  • Daemon status:
  • Use main.py status to check running daemons
  • Use main.py stop <bot|scheduler> to stop a daemon
  • Common issues:
  • Missing environment variables cause configuration errors
  • MongoDB connectivity failures require verifying MONGO_CONNECTION_STR
  • Telegram bot token or chat ID misconfiguration affects message delivery
  • Web push requires VAPID keys; missing keys disable web push

Conclusion#

Bot for humans, webhook for machines, scheduler for the clock. Shared DatabaseService and NotificationService underneath so you do not grow three data layers.

Appendices#

Deployment considerations#

  • Choose deployment option based on environment and scale (Local/VPS, Docker, GitHub Actions, cloud platforms)
  • Use systemd or PM2 for process supervision and automatic restarts
  • Configure reverse proxy for webhook deployments and SSL certificates
  • Enable log rotation and automated backups for MongoDB

Scaling strategies#

  • Horizontal scaling:
  • Run multiple instances of the webhook server behind a load balancer
  • Use Kubernetes deployments with readiness/liveness probes
  • Database scaling:
  • Enable MongoDB sharding for high-volume collections
  • Operational scaling:
  • Separate bot and scheduler instances for independent scaling
  • Use separate process managers for each server

Monitoring approaches#

  • Health endpoints:
  • Use /health for liveness/readiness checks
  • Logging:
  • Tail logs for errors and warnings
  • Alerts:
  • Monitor health externally and send alerts on failure
  • Metrics:
  • Track unsent notices and send success/failure ratios