API gateway of the system. Accepts requests from the web client, manages server monitoring configuration, streams real-time status updates via WebSocket, and routes notification events to delivery workers.
This repo is one of eight that make up the system:
| Repository | Stack | Role |
|---|---|---|
| api (this repo) | C# / ASP.NET Core, MediatR, SignalR | REST API, WebSocket hub, auth, notification routing |
| frontend | React 19, TypeScript, Vite, Radix UI, Recharts | Web UI: server management, live status, charts |
| ping-service | Go | Concurrent health checks (HTTP/TCP/ICMP), one goroutine per target |
| state-elevator | C# / .NET Worker | Status lifecycle evaluation, failure threshold detection |
| metrics-writer | C# / .NET Worker | Batched bulk insert of ping records to ClickHouse |
| email-service | C# / .NET Worker, MailKit, Polly | SMTP notification delivery with retry & circuit breaker |
| tg-bot | Python / FastAPI, aiogram, faststream | Telegram bot: webhook/polling & notification delivery |
| infra | Traefik, PostgreSQL, ClickHouse, Redis, RabbitMQ | Reverse proxy, all datastores, log aggregation |
The system consists of 6 independent services communicating via RabbitMQ (see the table above); this repo is the API — the only service the frontend talks to directly.
PostgreSQL (owned by this service): servers, ping_settings, user,
tokens, telegram_accounts, notification_settings
ClickHouse (read-only from here, written by Metrics Writer):
server_pings — per-ping record with latency_ms, rtt_min_ms,
rtt_max_ms, packet_loss_percent, cert_expires_at, tls_version,
dns_lookup_ms, sent_bytes, received_bytes, ttl, is_success,
status_code, error_message
- C# / ASP.NET Core 10 — Clean Architecture (Domain → Application → Infrastructure → Presentation)
- MediatR — CQRS, pipeline behaviors (validation, transaction, logging)
- Entity Framework Core + PostgreSQL — transactional data: users, servers, ping settings, tokens
- SignalR — WebSocket hub for real-time status push to the frontend
- RabbitMQ — publishes server lifecycle events; consumes status change events
- ClickHouse — read-only queries for ping history, uptime stats, and chart data
- Redis — per-user notification cooldown store
Frontend (Vue/React)
│ REST + WebSocket (SignalR)
▼
[ API ] ──publishes──▶ serverEventsExchange ──▶ Ping Service
│ ──▶ State Elevator
│
├── consumes ◀── statusEventsExchange ◀── State Elevator
│ └── updates PostgreSQL, pushes SignalR, sends notifications
│
├── publishes ──▶ emailQueue ──▶ Email Sender
└── publishes ──▶ telegramQueue ──▶ Telegram Bot
Auth POST /api/auth/{register, login, logout, refresh, verify-email, forgot-password, reset-password, resend-verification-code}
Servers
| Method | Path | Description |
|---|---|---|
GET |
/api/servers |
List servers (with optional ?search=) |
POST |
/api/servers |
Create server |
GET |
/api/servers/{id} |
Get server by id |
PUT |
/api/servers/{id} |
Update server |
DELETE |
/api/servers/{id} |
Delete server |
GET |
/api/servers/{id}/settings |
Get ping settings |
PATCH |
/api/servers/{id}/settings |
Update ping settings |
GET |
/api/servers/{id}/state |
Get current status from Redis |
GET |
/api/servers/{id}/pings |
Ping history from ClickHouse |
GET |
/api/servers/{id}/overview |
Aggregated chart + uptime stats |
Users
| Method | Path | Description |
|---|---|---|
GET |
/api/users/me |
Current user profile |
GET |
/api/users/notification-settings |
Notification preferences |
PATCH |
/api/users/notification-settings |
Update preferences |
Telegram GET/POST/DELETE /api/telegram-accounts
WebSocket ws://.../hubs/monitoring — SignalR hub, emits ServerStatusChanged events
cp .env.example .env
# fill in connection strings, JWT secret, SMTP credentials, RabbitMQ URL
docker compose upThe service runs on port 8080 and exposes a Swagger UI at /swagger.
# unit tests
dotnet test tests/Api.UnitTests
# integration tests (requires running infra)
dotnet test tests/Api.IntegrationTests
