Обновил документацию.

This commit is contained in:
ruberoid 2025-10-16 22:11:06 +04:00
parent 32b0253981
commit 15519f2377
4 changed files with 1183 additions and 359 deletions

View File

@ -1,48 +1,48 @@
# Configuration Guide # Руководство по конфигурации
This document describes how to configure the NOCR microservices system for different deployment scenarios. Этот документ описывает, как настроить микросервисную систему NOCR для различных сценариев развертывания.
## Table of Contents ## Содержание
1. [Configuration System Overview](#configuration-system-overview) 1. [Обзор системы конфигурации](#обзор-системы-конфигурации)
2. [Deployment Scenarios](#deployment-scenarios) 2. [Сценарии развертывания](#сценарии-развертывания)
- [Local Development (VS Code)](#local-development-vs-code) - [Локальная разработка (VS Code)](#локальная-разработка-vs-code)
- [Docker Compose](#docker-compose) - [Docker Compose](#docker-compose)
- [Kubernetes](#kubernetes) - [Kubernetes](#kubernetes)
3. [Configuration Priority](#configuration-priority) 3. [Приоритет конфигурации](#приоритет-конфигурации)
4. [Service-Specific Settings](#service-specific-settings) 4. [Настройки для конкретных сервисов](#настройки-для-конкретных-сервисов)
5. [Debug Mode](#debug-mode) 5. [Режим отладки](#режим-отладки)
6. [Troubleshooting](#troubleshooting) 6. [Устранение неполадок](#устранение-неполадок)
--- ---
## Configuration System Overview ## Обзор системы конфигурации
The system uses ASP.NET Core's layered configuration approach with the following sources (listed from lowest to highest priority): Система использует многоуровневый подход конфигурации ASP.NET Core со следующими источниками (от низшего к высшему приоритету):
1. `appsettings.json` - Base configuration (committed to git) 1. `appsettings.json` - Базовая конфигурация (коммитится в git)
2. `appsettings.{Environment}.json` - Environment-specific settings (some committed, some not) 2. `appsettings.{Environment}.json` - Настройки для конкретного окружения (некоторые коммитятся, некоторые нет)
3. User Secrets - Development-only secrets (stored locally, not in git) 3. User Secrets - Секреты только для разработки (хранятся локально, не в git)
4. **Environment Variables** - **Highest priority** (overrides everything) 4. **Переменные окружения** - **Наивысший приоритет** (переопределяют всё)
### Important Notes ### Важные примечания
- **Never commit secrets to git** - **Никогда не коммитьте секреты в git**
- Use `.example` files as templates - Используйте файлы `.example` как шаблоны
- Environment Variables always win in priority - Переменные окружения всегда имеют наивысший приоритет
- Each service has its own configuration requirements - Каждый сервис имеет свои требования к конфигурации
--- ---
## Deployment Scenarios ## Сценарии развертывания
### Local Development (VS Code) ### Локальная разработка (VS Code)
For debugging services individually in VS Code: Для отладки отдельных сервисов в VS Code:
#### Step 1: Create Environment-Specific Configuration #### Шаг 1: Создание конфигурации для окружения
For each service you want to run, create `appsettings.Development.json` from the example: Для каждого сервиса, который вы хотите запустить, создайте `appsettings.Development.json` из примера:
```bash ```bash
# Telegram Listener # Telegram Listener
@ -62,11 +62,11 @@ cd telegram-client/src/Nocr.TelegramClient.Host
cp appsettings.Development.json.example appsettings.Development.json cp appsettings.Development.json.example appsettings.Development.json
``` ```
#### Step 2: Fill in Your Values #### Шаг 2: Заполните ваши значения
Edit each `appsettings.Development.json` file and replace placeholder values with your actual credentials. Отредактируйте каждый файл `appsettings.Development.json` и замените placeholder-значения на ваши реальные учетные данные.
**Example for Telegram Listener:** **Пример для Telegram Listener:**
```json ```json
{ {
"RebusRabbitMqOptions": { "RebusRabbitMqOptions": {
@ -80,13 +80,13 @@ Edit each `appsettings.Development.json` file and replace placeholder values wit
} }
``` ```
#### Step 3: Alternative - Use Environment Variables #### Шаг 3: Альтернатива - использование переменных окружения
Instead of creating `appsettings.Development.json`, you can use environment variables in `.vscode/launch.json`: Вместо создания `appsettings.Development.json`, вы можете использовать переменные окружения в `.vscode/launch.json`:
```json ```json
{ {
"name": "Launch Service", "name": "Запуск сервиса",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"env": { "env": {
@ -99,57 +99,57 @@ Instead of creating `appsettings.Development.json`, you can use environment vari
} }
``` ```
**Note:** Use double underscores `__` to represent nested configuration sections in environment variables. **Примечание:** Используйте двойное подчеркивание `__` для представления вложенных секций конфигурации в переменных окружения.
#### Step 4: Start Infrastructure #### Шаг 4: Запуск инфраструктуры
You need RabbitMQ and databases running: Вам нужны работающие RabbitMQ и базы данных:
```bash ```bash
# Start only infrastructure services # Запустить только инфраструктурные сервисы
docker-compose up nocr-rabbitmq nocr-text-matcher-db nocr-users-db -d docker-compose up nocr-rabbitmq nocr-text-matcher-db nocr-users-db -d
``` ```
#### Step 5: Debug in VS Code #### Шаг 5: Отладка в VS Code
Press F5 or use the Run and Debug panel to start your service. Нажмите F5 или используйте панель Run and Debug для запуска вашего сервиса.
--- ---
### Docker Compose ### Docker Compose
For running the entire system locally with Docker: Для запуска всей системы локально с Docker:
#### Step 1: Create .nocr.env File #### Шаг 1: Создание файла .nocr.env
```bash ```bash
cd /path/to/project/root cd /путь/к/корню/проекта
cp .nocr.env.example .nocr.env cp .nocr.env.example .nocr.env
``` ```
#### Step 2: Edit .nocr.env #### Шаг 2: Редактирование .nocr.env
Open `.nocr.env` and fill in your actual credentials: Откройте `.nocr.env` и заполните ваши реальные учетные данные:
```bash ```bash
# Telegram Listener - get from https://my.telegram.org/apps # Telegram Listener - получить на https://my.telegram.org/apps
WTelegramClientOptions__ApiId=22101230 WTelegramClientOptions__ApiId=22101230
WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b
WTelegramClientOptions__PhoneNumber=79167310711 WTelegramClientOptions__PhoneNumber=79167310711
# Telegram Client Bot - get from @BotFather # Telegram Client Bot - получить у @BotFather
TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz
# Optional: Enable debug logging # Опционально: включить отладочное логирование
# NOCR_DEBUG_MODE=true # NOCR_DEBUG_MODE=true
``` ```
#### Step 3: Create DockerCompose Configuration Files #### Шаг 3: Создание конфигурационных файлов для DockerCompose
Each service needs `appsettings.DockerCompose.json`: Каждому сервису нужен `appsettings.DockerCompose.json`:
```bash ```bash
# For each service # Для каждого сервиса
cd telegram-listener/src/Nocr.TelegramListener.Host cd telegram-listener/src/Nocr.TelegramListener.Host
cp appsettings.DockerCompose.json.example appsettings.DockerCompose.json cp appsettings.DockerCompose.json.example appsettings.DockerCompose.json
@ -163,21 +163,21 @@ cd telegram-client/src/Nocr.TelegramClient.Host
cp appsettings.DockerCompose.json.example appsettings.DockerCompose.json cp appsettings.DockerCompose.json.example appsettings.DockerCompose.json
``` ```
**Note:** These files contain Docker network hostnames (e.g., `nocr-rabbitmq:5672` instead of `localhost:5672`). **Примечание:** Эти файлы содержат имена хостов Docker-сети (например, `nocr-rabbitmq:5672` вместо `localhost:5672`).
#### Step 4: Start All Services #### Шаг 4: Запуск всех сервисов
```bash ```bash
docker-compose up docker-compose up
``` ```
Or build and start: Или со сборкой:
```bash ```bash
docker-compose up --build docker-compose up --build
``` ```
#### Step 5: Verify Services are Running #### Шаг 5: Проверка работоспособности сервисов
- Telegram Listener: http://localhost:5040/health - Telegram Listener: http://localhost:5040/health
- Text Matcher: http://localhost:5041/health - Text Matcher: http://localhost:5041/health
@ -189,32 +189,32 @@ docker-compose up --build
### Kubernetes ### Kubernetes
For production deployment on Kubernetes: Для production-развертывания на Kubernetes:
#### Step 1: Create Kubernetes Secrets #### Шаг 1: Создание Kubernetes Secrets
**Do NOT use `.nocr.env` file in K8s.** Instead, create Secrets: **НЕ используйте файл `.nocr.env` в K8s.** Вместо этого создайте Secrets:
```bash ```bash
# Create namespace # Создать namespace
kubectl create namespace nocr kubectl create namespace nocr
# Create secrets for Telegram Listener # Создать secrets для Telegram Listener
kubectl create secret generic telegram-listener-secrets \ kubectl create secret generic telegram-listener-secrets \
--from-literal=WTelegramClientOptions__ApiId=22101230 \ --from-literal=WTelegramClientOptions__ApiId=22101230 \
--from-literal=WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b \ --from-literal=WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b \
--from-literal=WTelegramClientOptions__PhoneNumber=79167310711 \ --from-literal=WTelegramClientOptions__PhoneNumber=79167310711 \
-n nocr -n nocr
# Create secrets for Telegram Client # Создать secrets для Telegram Client
kubectl create secret generic telegram-client-secrets \ kubectl create secret generic telegram-client-secrets \
--from-literal=TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz \ --from-literal=TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz \
-n nocr -n nocr
``` ```
#### Step 2: Reference Secrets in Deployment #### Шаг 2: Ссылка на Secrets в Deployment
Example Kubernetes deployment manifest: Пример манифеста Kubernetes deployment:
```yaml ```yaml
apiVersion: apps/v1 apiVersion: apps/v1
@ -236,9 +236,9 @@ spec:
name: telegram-listener-secrets name: telegram-listener-secrets
``` ```
#### Step 3: Create appsettings.Production.json #### Шаг 3: Создание appsettings.Production.json
Create production config files with K8s service names: Создайте production-конфигурационные файлы с именами сервисов K8s:
```json ```json
{ {
@ -248,9 +248,9 @@ Create production config files with K8s service names:
} }
``` ```
**Note:** Secrets from environment variables will override these values. **Примечание:** Секреты из переменных окружения переопределят эти значения.
#### Step 4: Deploy #### Шаг 4: Деплой
```bash ```bash
kubectl apply -f deployment/ kubectl apply -f deployment/
@ -258,36 +258,36 @@ kubectl apply -f deployment/
--- ---
## Configuration Priority ## Приоритет конфигурации
Understanding priority is crucial when troubleshooting configuration issues. Понимание приоритета критически важно при устранении проблем с конфигурацией.
### Priority Order (Lowest → Highest) ### Порядок приоритета (от низшего к высшему)
1. ⬇️ `appsettings.json` (base) 1. ⬇️ `appsettings.json` (базовый)
2. ⬆️ `appsettings.{Environment}.json` (e.g., Development, DockerCompose, Production) 2. ⬆️ `appsettings.{Environment}.json` (например, Development, DockerCompose, Production)
3. ⬆️ User Secrets (Development only) 3. ⬆️ User Secrets (только Development)
4. ⬆️⬆️ **Environment Variables (ALWAYS WINS)** 4. ⬆️⬆️ **Переменные окружения (ВСЕГДА ВЫИГРЫВАЮТ)**
### Example Scenario ### Пример сценария
If you have: Если у вас есть:
- `appsettings.json`: `"ConnectionString": ""` - `appsettings.json`: `"ConnectionString": ""`
- `appsettings.DockerCompose.json`: `"ConnectionString": "amqp://admin:admin@nocr-rabbitmq:5672/"` - `appsettings.DockerCompose.json`: `"ConnectionString": "amqp://admin:admin@nocr-rabbitmq:5672/"`
- Environment Variable: `RebusRabbitMqOptions__ConnectionString=amqp://admin:admin@localhost:5672/` - Переменная окружения: `RebusRabbitMqOptions__ConnectionString=amqp://admin:admin@localhost:5672/`
**Result:** Environment variable wins! Connection will use `localhost:5672`. **Результат:** Переменная окружения побеждает! Подключение будет использовать `localhost:5672`.
This is why we removed `appsettings.protected.json` - it was overriding Docker Compose settings incorrectly. Именно поэтому мы удалили `appsettings.protected.json` - он неправильно переопределял настройки Docker Compose.
--- ---
## Service-Specific Settings ## Настройки для конкретных сервисов
### Telegram Listener ### Telegram Listener
**Required Configuration:** **Обязательная конфигурация:**
```json ```json
{ {
@ -302,17 +302,17 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
} }
``` ```
**How to obtain Telegram credentials:** **Как получить учетные данные Telegram:**
1. Visit https://my.telegram.org/apps 1. Посетите https://my.telegram.org/apps
2. Log in with your phone number 2. Войдите с вашим номером телефона
3. Create a new application 3. Создайте новое приложение
4. Copy `api_id` and `api_hash` 4. Скопируйте `api_id` и `api_hash`
--- ---
### Text Matcher ### Text Matcher
**Required Configuration:** **Обязательная конфигурация:**
```json ```json
{ {
@ -325,7 +325,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
} }
``` ```
**Ports by environment:** **Порты по окружениям:**
- Development: `localhost:3316` - Development: `localhost:3316`
- Docker Compose: `nocr-text-matcher-db:3306` - Docker Compose: `nocr-text-matcher-db:3306`
- Kubernetes: `text-matcher-db-service:3306` - Kubernetes: `text-matcher-db-service:3306`
@ -334,7 +334,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
### Users ### Users
**Required Configuration:** **Обязательная конфигурация:**
```json ```json
{ {
@ -344,7 +344,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
} }
``` ```
**Ports by environment:** **Порты по окружениям:**
- Development: `localhost:3326` - Development: `localhost:3326`
- Docker Compose: `nocr-users-db:3306` - Docker Compose: `nocr-users-db:3306`
- Kubernetes: `users-db-service:3306` - Kubernetes: `users-db-service:3306`
@ -353,7 +353,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
### Telegram Client ### Telegram Client
**Required Configuration:** **Обязательная конфигурация:**
```json ```json
{ {
@ -372,45 +372,45 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
} }
``` ```
**How to obtain Bot Token:** **Как получить Bot Token:**
1. Open Telegram and find @BotFather 1. Откройте Telegram и найдите @BotFather
2. Send `/newbot` command 2. Отправьте команду `/newbot`
3. Follow instructions to create your bot 3. Следуйте инструкциям для создания вашего бота
4. Copy the token provided 4. Скопируйте предоставленный токен
--- ---
## Debug Mode ## Режим отладки
Enable debug mode to print masked configuration values on startup. Включите режим отладки для вывода маскированных значений конфигурации при запуске.
### How to Enable ### Как включить
Set environment variable: Установите переменную окружения:
```bash ```bash
export NOCR_DEBUG_MODE=true export NOCR_DEBUG_MODE=true
``` ```
Or in `.nocr.env`: Или в `.nocr.env`:
```bash ```bash
NOCR_DEBUG_MODE=true NOCR_DEBUG_MODE=true
``` ```
Or in `docker-compose.yml`: Или в `docker-compose.yml`:
```yaml ```yaml
environment: environment:
NOCR_DEBUG_MODE: "true" NOCR_DEBUG_MODE: "true"
``` ```
### Example Output ### Пример вывода
When debug mode is enabled, you'll see masked configuration on startup: Когда режим отладки включен, вы увидите маскированную конфигурацию при запуске:
``` ```
=== [NOCR_DEBUG] Configuration Values === === [NOCR_DEBUG] Значения конфигурации ===
[NOCR_DEBUG] RebusRabbitMqOptions: [NOCR_DEBUG] RebusRabbitMqOptions:
[NOCR_DEBUG] ConnectionString: amqp://admin:***@nocr-rabbitmq:5672/ [NOCR_DEBUG] ConnectionString: amqp://admin:***@nocr-rabbitmq:5672/
[NOCR_DEBUG] InputQueueName: nocr.telegram.listener.queue [NOCR_DEBUG] InputQueueName: nocr.telegram.listener.queue
@ -420,144 +420,144 @@ When debug mode is enabled, you'll see masked configuration on startup:
[NOCR_DEBUG] ApiId: 22101230 [NOCR_DEBUG] ApiId: 22101230
[NOCR_DEBUG] ApiHash: c7...0b [NOCR_DEBUG] ApiHash: c7...0b
[NOCR_DEBUG] PhoneNumber: 79...11 [NOCR_DEBUG] PhoneNumber: 79...11
=== [NOCR_DEBUG] End Configuration === === [NOCR_DEBUG] Конец конфигурации ===
``` ```
**Security:** Passwords and secrets are automatically masked to protect sensitive data. **Безопасность:** Пароли и секреты автоматически маскируются для защиты конфиденциальных данных.
--- ---
## Troubleshooting ## Устранение неполадок
### Problem: Service can't connect to RabbitMQ ### Проблема: Сервис не может подключиться к RabbitMQ
**Symptoms:** **Симптомы:**
``` ```
Connection refused to nocr-rabbitmq:5672 Connection refused to nocr-rabbitmq:5672
``` ```
**Solution:** **Решение:**
1. Check if RabbitMQ is running: `docker-compose ps nocr-rabbitmq` 1. Проверьте, работает ли RabbitMQ: `docker-compose ps nocr-rabbitmq`
2. Enable debug mode: `NOCR_DEBUG_MODE=true` 2. Включите режим отладки: `NOCR_DEBUG_MODE=true`
3. Verify ConnectionString in debug output 3. Проверьте ConnectionString в выводе отладки
4. For Docker Compose, ensure hostname is `nocr-rabbitmq:5672`, NOT `localhost:5672` 4. Для Docker Compose убедитесь, что hostname - `nocr-rabbitmq:5672`, НЕ `localhost:5672`
5. Check if environment variable is overriding appsettings 5. Проверьте, не переопределяет ли переменная окружения appsettings
--- ---
### Problem: Service can't connect to database ### Проблема: Сервис не может подключиться к базе данных
**Symptoms:** **Симптомы:**
``` ```
Unable to connect to any of the specified MySQL hosts Unable to connect to any of the specified MySQL hosts
``` ```
**Solution:** **Решение:**
1. Check database is running: `docker-compose ps nocr-text-matcher-db` 1. Проверьте, что база данных запущена: `docker-compose ps nocr-text-matcher-db`
2. Enable debug mode to see masked connection string 2. Включите режим отладки для просмотра маскированной строки подключения
3. Verify hostname in connection string: 3. Проверьте hostname в строке подключения:
- Docker Compose: `nocr-text-matcher-db:3306` - Docker Compose: `nocr-text-matcher-db:3306`
- Local dev: `localhost:3316` - Локальная разработка: `localhost:3316`
4. Wait for database healthcheck to pass (may take 10-30 seconds on first start) 4. Подождите прохождения healthcheck (может занять 10-30 секунд при первом запуске)
--- ---
### Problem: Configuration values not applied ### Проблема: Значения конфигурации не применяются
**Symptoms:** **Симптомы:**
- Settings in `appsettings.Development.json` are ignored - Настройки в `appsettings.Development.json` игнорируются
- Service uses wrong configuration - Сервис использует неправильную конфигурацию
**Solution:** **Решение:**
1. Check `ASPNETCORE_ENVIRONMENT` is set correctly: 1. Проверьте, что `ASPNETCORE_ENVIRONMENT` установлен правильно:
- VS Code: `Development` - VS Code: `Development`
- Docker Compose: `DockerCompose` - Docker Compose: `DockerCompose`
- K8s: `Production` - K8s: `Production`
2. Enable debug mode to see which values are loaded 2. Включите режим отладки для просмотра загруженных значений
3. Check for environment variables overriding your settings 3. Проверьте переменные окружения, переопределяющие ваши настройки
4. Remember: **Environment Variables always win!** 4. Помните: **Переменные окружения всегда выигрывают!**
--- ---
### Problem: Secrets exposed in logs ### Проблема: Секреты раскрыты в логах
**Solution:** **Решение:**
- Debug mode automatically masks sensitive values - Режим отладки автоматически маскирует конфиденциальные значения
- Never log configuration in production without masking - Никогда не логируйте конфигурацию в production без маскировки
- Review debug output format in `Startup.cs`: - Проверьте формат вывода отладки в `Startup.cs`:
- Passwords: `amqp://user:***@host` - Пароли: `amqp://user:***@host`
- Secrets: `ab...yz` (first 2 + last 2 chars only) - Секреты: `ab...yz` (только первые 2 + последние 2 символа)
--- ---
### Problem: Missing .nocr.env file ### Проблема: Отсутствует файл .nocr.env
**Symptoms:** **Симптомы:**
``` ```
docker-compose up fails with missing environment variables docker-compose up падает с ошибкой отсутствующих переменных окружения
``` ```
**Solution:** **Решение:**
1. Copy example file: `cp .nocr.env.example .nocr.env` 1. Скопируйте файл-пример: `cp .nocr.env.example .nocr.env`
2. Fill in your actual values 2. Заполните ваши реальные значения
3. Make sure `.nocr.env` is in the project root (same level as `docker-compose.yml`) 3. Убедитесь, что `.nocr.env` находится в корне проекта (на том же уровне, что и `docker-compose.yml`)
--- ---
## Quick Reference ## Краткая справка
### Environment Variable Naming Convention ### Соглашение об именовании переменных окружения
ASP.NET Core uses double underscores `__` to represent nested JSON structure: ASP.NET Core использует двойное подчеркивание `__` для представления вложенной JSON-структуры:
```bash ```bash
# JSON: { "Section": { "Key": "Value" } } # JSON: { "Section": { "Key": "Value" } }
# Environment Variable: # Переменная окружения:
Section__Key=Value Section__Key=Value
# Example: # Примеры:
WTelegramClientOptions__ApiId=12345 WTelegramClientOptions__ApiId=12345
RebusRabbitMqOptions__ConnectionString=amqp://localhost RebusRabbitMqOptions__ConnectionString=amqp://localhost
``` ```
### File Locations ### Расположение файлов
``` ```
flea/ # Project root flea/ # Корень проекта
├── .nocr.env # Your secrets (gitignored) ├── .nocr.env # Ваши секреты (gitignored)
├── .nocr.env.example # Template (committed) ├── .nocr.env.example # Шаблон (коммитится)
├── docker-compose.yml # References .nocr.env ├── docker-compose.yml # Ссылается на .nocr.env
├── telegram-listener/ ├── telegram-listener/
│ └── src/Nocr.TelegramListener.Host/ │ └── src/Nocr.TelegramListener.Host/
│ ├── appsettings.json # Base (committed) │ ├── appsettings.json # Базовый (коммитится)
│ ├── appsettings.Development.json # Local dev (gitignored) │ ├── appsettings.Development.json # Локальная разработка (gitignored)
│ ├── appsettings.Development.json.example # Template (committed) │ ├── appsettings.Development.json.example # Шаблон (коммитится)
│ ├── appsettings.DockerCompose.json # Docker (gitignored) │ ├── appsettings.DockerCompose.json # Docker (gitignored)
│ └── appsettings.DockerCompose.json.example # Template (committed) │ └── appsettings.DockerCompose.json.example # Шаблон (коммитится)
└── [same structure for text-matcher, users, telegram-client] └── [та же структура для text-matcher, users, telegram-client]
``` ```
--- ---
## Security Best Practices ## Рекомендации по безопасности
1. ✅ **Never commit secrets** - Use `.example` files as templates 1. ✅ **Никогда не коммитьте секреты** - используйте файлы `.example` как шаблоны
2. ✅ **Use environment variables** for sensitive data in production 2. ✅ **Используйте переменные окружения** для конфиденциальных данных в production
3. ✅ **Use K8s Secrets** for Kubernetes deployments 3. ✅ **Используйте K8s Secrets** для развертывания в Kubernetes
4. ✅ **Enable debug mode** only when troubleshooting 4. ✅ **Включайте режим отладки** только при устранении неполадок
5. ✅ **Rotate credentials** regularly 5. ✅ **Ротируйте учетные данные** регулярно
6. ✅ **Use User Secrets** for local development (optional) 6. ✅ **Используйте User Secrets** для локальной разработки (опционально)
7. ❌ **Don't commit** `.nocr.env` or `appsettings.*.json` (except `.example` files) 7. ❌ **Не коммитьте** `.nocr.env` или `appsettings.*.json` (кроме файлов `.example`)
8. ❌ **Don't use** `appsettings.protected.json` (removed from code) 8. ❌ **Не используйте** `appsettings.protected.json` (удален из кода)
--- ---
## Additional Resources ## Дополнительные ресурсы
- [ASP.NET Core Configuration Docs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) - [Документация конфигурации ASP.NET Core](https://learn.microsoft.com/ru-ru/aspnet/core/fundamentals/configuration/)
- [Docker Compose Environment Variables](https://docs.docker.com/compose/environment-variables/) - [Переменные окружения Docker Compose](https://docs.docker.com/compose/environment-variables/)
- [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) - [Kubernetes Secrets](https://kubernetes.io/ru/docs/concepts/configuration/secret/)
- [Telegram API Documentation](https://core.telegram.org/api) - [Документация Telegram API](https://core.telegram.org/api)
- [Telegram Bot API](https://core.telegram.org/bots/api) - [Telegram Bot API](https://core.telegram.org/bots/api)

450
README.md
View File

@ -1,22 +1,446 @@
# Спец проект для работы с зависимостями, внешними и внутренними сервисами и приложениями. # NOCR - Система мониторинга Telegram-каналов
Аккумуляция всех вложенных проектов. [![Build Status](https://drone.musk.fun/api/badges/nocr/flea/status.svg?ref=refs/heads/main)](https://drone.musk.fun/nocr/flea)
[telegram-listener](https://gitea.musk.fun/nocr/telegram-listener) Микросервисная система на базе Telegram Bot для мониторинга и уведомлений о текстовых совпадениях в открытых каналах и чатах.
Модуль, отвечающий за скан открытых каналов и чатов.
[telegram-client](https://gitea.musk.fun/nocr/telegram-client) ## 📋 Обзор проекта
Модуль, отвечающий за клиентский интерфейс самого бота взаимодействия с пользователем.
[users](https://gitea.musk.fun/nocr/users) Это родительский проект, содержащий все сервисы как **git submodules**. Каждый сервис является отдельным репозиторием, что обеспечивает независимую разработку и версионирование.
Модуль, отвечающий за управление пользователями сервиса и их предпочтениями.
[text-matcher](https://gitea.musk.fun/nocr/text-matcher) ### Архитектура сервисов
Модуль, отвечающий за сравнивание всего объема подписанных сообщений через listener по пересечению с пользовательскими интересами.
Система состоит из 4 основных микросервисов, взаимодействующих через RabbitMQ:
#### 1. [telegram-listener](https://gitea.musk.fun/nocr/telegram-listener)
**Назначение:** Сканирование открытых Telegram-каналов и чатов
- Подписка на каналы через Telegram MTProto API
- Публикация событий о новых и отредактированных сообщениях в message bus
- Хранение сессий пользователей
#### 2. [text-matcher](https://gitea.musk.fun/nocr/text-matcher)
**Назначение:** Сопоставление сообщений с пользовательскими подписками
- Обработка событий от telegram-listener
- Проверка совпадений по регулярным выражениям и ключевым словам
- Хранение истории совпадений в БД (MariaDB)
- Публикация событий о найденных совпадениях
#### 3. [telegram-client](https://gitea.musk.fun/nocr/telegram-client)
**Назначение:** Клиентский интерфейс бота для взаимодействия с пользователями
- Прием команд от пользователей через Telegram Bot API
- Управление подписками на каналы
- Отправка уведомлений о найденных совпадениях
- Интеграция с users и text-matcher через REST API
#### 4. [users](https://gitea.musk.fun/nocr/users)
**Назначение:** Управление пользователями и их настройками
- CRUD операции для пользователей
- Хранение предпочтений и подписок
- REST API для других сервисов
--- ---
docker-compose.yml файл используется для старта проектов и зависисмостей внутри докера. Конфигурация хостовых сервисов опирается на конфигурационный файл общего назначения `appsettings.json` и специфичный для докера `appsettings.DockerCompose.json` (частный файл). Однако общие чувствительные для всех видов запуска секреты хранятся в `appsettings.protected.json`. Для личного пользования и отдельного запуска проектов необходимо двигаться по пути `appsettings.Development.json`. ## 🚀 Быстрый старт
# Статус сборки drone: ### Вариант 1: Docker Compose (рекомендуется)
[![Build Status](https://drone.musk.fun/api/badges/nocr/flea/status.svg?ref=refs/heads/main)](https://drone.musk.fun/nocr/flea)
```bash
# 1. Создайте файл с секретами
cp .nocr.env.example .nocr.env
# 2. Заполните ваши Telegram API ключи в .nocr.env
# - API ID и Hash: https://my.telegram.org/apps
# - Bot Token: @BotFather в Telegram
# 3. Запустите все сервисы
docker-compose up
```
**Проверка работоспособности:**
- Telegram Listener: http://localhost:5040/health
- Text Matcher: http://localhost:5041/health
- Users: http://localhost:5042/health
- Telegram Client: http://localhost:5050/health
- RabbitMQ UI: http://localhost:15672 (admin/admin)
### Вариант 2: Локальная разработка (VS Code)
```bash
# 1. Запустите инфраструктуру (RabbitMQ + базы данных)
docker-compose up nocr-rabbitmq nocr-text-matcher-db nocr-users-db -d
# 2. Создайте конфигурационные файлы для каждого сервиса
cd telegram-listener/src/Nocr.TelegramListener.Host
cp appsettings.Development.json.example appsettings.Development.json
# Повторите для всех сервисов
# 3. Заполните ваши секреты в appsettings.Development.json
# 4. Запустите сервисы через VS Code (F5)
```
**📖 Подробная документация:** См. [CONFIGURATION.md](CONFIGURATION.md)
---
## 🏗️ Архитектура взаимодействия
```
┌──────────────────┐ ┌───────────────┐ ┌──────────────────┐
│ Telegram Channel │────────▶│ Listener │────────▶│ Text Matcher │
│ (MTProto API) │ │ (Scan msgs) │ │ (Match rules) │
└──────────────────┘ └───────┬───────┘ └────────┬─────────┘
│ │
│ │
│ RabbitMQ │
│ Message Bus │
│ │
▼ ▼
┌───────────────┐ ┌──────────────────┐
│ Event Topics │ │ Telegram Bot │
& Queues │◀────────│ Client │
└───────────────┘ │ (Notifications) │
└──────────────────┘
┌──────────────────┐
│ Users Service │
│ (User Management)│
└──────────────────┘
```
**Паттерн взаимодействия:**
- **Event-driven**: Асинхронная обработка через RabbitMQ
- **REST API**: Синхронные запросы между telegram-client и другими сервисами
- **Clean Architecture**: Разделение на слои Host/AppServices/Core/Persistence
**📖 Подробная диаграмма:** См. [architecture.md](architecture.md)
---
## 🔧 Технологический стек
- **.NET 8** - Фреймворк для всех сервисов
- **ASP.NET Core** - Web API
- **Entity Framework Core** - ORM для MariaDB
- **WTelegramClient** - MTProto API для telegram-listener
- **Telegram.Bot** - Bot API для telegram-client
- **Rebus** - Message bus поверх RabbitMQ
- **MariaDB** - Базы данных для text-matcher и users
- **RabbitMQ** - Брокер сообщений
- **Docker & Docker Compose** - Контейнеризация
- **Drone CI** - CI/CD на Kubernetes
---
## 📦 CI/CD Pipeline
Проект использует **Drone CI** с 5 специализированными пайплайнами:
### 1. 🧪 Feature Validation
**Триггер:** Push в ветки `feature/*`, `fix/*`, `issues/*`
**Длительность:** ~3-5 минут
- Сборка всех сервисов
- Запуск тестов с Testcontainers
- Быстрая обратная связь перед PR
### 2. ✅ Main Validation
**Триггер:** Push в ветку `main`
**Длительность:** ~3-5 минут
- Валидация после мерджа в main
- Гарантия стабильности основной ветки
### 3. 📝 Contracts-Only Publish
**Триггер:** Tag с сообщением `contracts_only:<service>`
**Длительность:** ~2 минуты
- Публикация NuGet-пакетов контрактов
- Без сборки Docker-образов
```bash
git commit -m "contracts_only:telegram_listener - Add MessageEdited event"
git tag v1.2.4-contracts && git push origin v1.2.4-contracts
```
### 4. 🚀 Full Release
**Триггер:** Tag без специальных маркеров
**Длительность:** ~8-10 минут
1. Публикация всех контрактов (параллельно)
2. Сборка Docker-образов с Kaniko (параллельно)
3. Деплой в Kubernetes (для тегов `v*`)
```bash
git tag v1.3.0 && git push origin v1.3.0
```
### 5. ⚡ Deploy-Only
**Триггер:** Tag с сообщением `deploy_only:`
**Длительность:** ~1 минута
- Деплой существующих образов без пересборки
- Откат к предыдущей версии
```bash
git commit --allow-empty -m "deploy_only: Rollback to v1.2.9"
git tag v1.2.9-deploy && git push origin v1.2.9-deploy
```
**📖 Полная документация CI/CD:** См. [_deploy/README.md](_deploy/README.md)
---
## 🛠️ Команды разработки
### Сборка
```bash
# Сборка конкретного сервиса
cd telegram-listener && dotnet build
# Сборка всех сервисов
dotnet build telegram-listener/Nocr.TelegramListener.sln
dotnet build telegram-client/Nocr.TelegramClient.sln
dotnet build text-matcher/Nocr.TextMatcher.sln
dotnet build users/Nocr.Users.sln
```
### Тестирование
```bash
# Запуск тестов (text-matcher)
cd text-matcher && dotnet test
```
### Миграции БД
```bash
# Добавить новую миграцию
cd text-matcher
./src/Nocr.TextMatcher.Migrator/AddMigration.sh MyMigrationName
cd users
./src/Nocr.Users.Migrator/AddMigration.sh MyMigrationName
# Применение миграций автоматически при запуске через docker-compose
```
### Работа с субмодулями
```bash
# Инициализация субмодулей после клонирования
git submodule update --init --recursive
# Обновление всех субмодулей до последних коммитов
git submodule update --remote --merge
# Автокоммит изменений в субмодулях (скрипт)
./commit-submodules.sh "Update submodules"
```
---
## 📊 Порты сервисов
При запуске через Docker Compose:
| Сервис | Порт | Health Check |
|--------|------|--------------|
| telegram-listener | 5040 | http://localhost:5040/health |
| text-matcher | 5041 | http://localhost:5041/health |
| users | 5042 | http://localhost:5042/health |
| telegram-client | 5050 | http://localhost:5050/health |
| RabbitMQ AMQP | 5672 | - |
| RabbitMQ Management | 15672 | http://localhost:15672 |
| MariaDB (text-matcher) | 3316 | - |
| MariaDB (users) | 3326 | - |
---
## 🔐 Конфигурация
### Приоритет источников конфигурации
1. **appsettings.json** (базовые настройки)
2. **appsettings.{Environment}.json** (Development/DockerCompose/Production)
3. **User Secrets** (только для Development)
4. **Environment Variables** ⬆️ **НАИВЫСШИЙ ПРИОРИТЕТ**
### Важные правила
- ❌ **Никогда не коммитьте секреты** в git
- ✅ Используйте файлы `.example` как шаблоны
- ✅ Environment Variables переопределяют все остальное
- ✅ Docker Compose использует `.nocr.env` (gitignored)
- ✅ Kubernetes использует Secrets
### Режим отладки
Для вывода маскированных значений конфигурации:
```bash
export NOCR_DEBUG_MODE=true
```
**📖 Полное руководство:** См. [CONFIGURATION.md](CONFIGURATION.md)
---
## 📚 Документация
- [CONFIGURATION.md](CONFIGURATION.md) - Подробное руководство по конфигурации
- [_deploy/README.md](_deploy/README.md) - CI/CD пайплайны и деплой
- [architecture.md](architecture.md) - Архитектурная диаграмма
- [CLAUDE.md](CLAUDE.md) - Инструкции для Claude Code AI
### Документация сервисов
- [telegram-listener/README.md](telegram-listener/README.md)
- [telegram-client/README.md](telegram-client/README.md)
- [text-matcher/README.md](text-matcher/README.md)
- [users/README.md](users/README.md)
---
## 🤝 Рабочий процесс разработки
### Создание новой функции
```bash
# 1. Создайте feature-ветку
git checkout -b feature/add-filter
# 2. Работайте в субмодуле
cd telegram-listener
git checkout -b feature/add-filter
# Внесите изменения...
git commit -m "Add new filter"
git push origin feature/add-filter
# 3. Обновите родительский проект
cd ..
git add telegram-listener
git commit -m "Update telegram-listener: Add new filter"
git push origin feature/add-filter
# 4. Создайте PR и дождитесь прохождения CI
```
### Релиз новой версии
```bash
# 1. Убедитесь, что все изменения в main
git checkout main && git pull
# 2. Создайте тег
git tag v1.4.0 -m "Release v1.4.0: New features"
git push origin v1.4.0
# 3. Drone автоматически:
# - Опубликует NuGet-пакеты
# - Соберет Docker-образы
# - Задеплоит в Kubernetes (для v* тегов)
```
---
## 🐛 Troubleshooting
### Сервис не подключается к RabbitMQ
```bash
# 1. Проверьте, что RabbitMQ запущен
docker-compose ps nocr-rabbitmq
# 2. Включите режим отладки
export NOCR_DEBUG_MODE=true
# 3. Проверьте ConnectionString в логах
# Для Docker: должно быть nocr-rabbitmq:5672, НЕ localhost:5672
```
### Ошибка подключения к базе данных
```bash
# 1. Проверьте статус БД
docker-compose ps nocr-text-matcher-db
# 2. Подождите прохождения healthcheck (10-30 сек при первом запуске)
# 3. Проверьте порт в connection string:
# - Docker: nocr-text-matcher-db:3306
# - Local: localhost:3316
```
### Pipeline падает на тестах
```bash
# 1. Проверьте, что Testcontainers может подключиться к Docker
# В pipeline должна быть переменная DOCKER_HOST
# 2. Запустите тесты локально
cd text-matcher
dotnet test
# 3. Проверьте логи в Drone UI
```
---
## 📈 Мониторинг
### Проверка здоровья сервисов
```bash
# Локально
curl http://localhost:5040/health # telegram-listener
curl http://localhost:5041/health # text-matcher
curl http://localhost:5042/health # users
curl http://localhost:5050/health # telegram-client
# В Kubernetes (из deploy pod)
cd _deploy/scripts
./health-check.sh
```
### Просмотр логов
```bash
# Docker Compose
docker-compose logs -f telegram-listener
docker-compose logs -f text-matcher
# Kubernetes
kubectl logs -f deployment/telegram-listener -n nocr
kubectl logs -f deployment/text-matcher -n nocr
```
---
## 📝 История изменений (15-16 октября 2025)
### Основные улучшения
- ✨ **Новый CI/CD**: 5 специализированных пайплайнов Drone
- 🔧 **Исправления .drone.yml**: Корректная обработка YAML с многострочными командами
- 📦 **Contracts-only пайплайн**: Быстрая публикация контрактов без пересборки образов
- 🚀 **Deploy-only пайплайн**: Быстрый откат и деплой существующих образов
- 🔄 **MessageEdited события**: Отдельная обработка отредактированных сообщений
- 📝 **Автокоммит субмодулей**: Скрипт для упрощения работы с субмодулями
- ⚡ **Оптимизации**: Shared NuGet cache, параллельная сборка, Kaniko caching
### Исправленные проблемы
- 🐛 Исправлен парсинг YAML в `.drone.yml` (строка 126)
- 🐛 Корректная обработка `${DRONE_COMMIT_SHA:0:7}` в командах
- 🐛 Правильные отступы в многострочных bash-скриптах
- 🐛 Зависимости между этапами pipeline
---
## 📄 Лицензия
[Укажите лицензию вашего проекта]
## 👥 Авторы
[Укажите авторов проекта]
---
**Дополнительные ссылки:**
- [Drone CI](https://drone.musk.fun/nocr/flea)
- [Gitea Repository](https://gitea.musk.fun/nocr/flea)

View File

@ -1,127 +1,127 @@
# 🚀 Nocr CI/CD Pipeline Documentation # 🚀 Документация CI/CD Pipeline NOCR
## 📋 Overview ## 📋 Обзор
The Nocr project uses a modern, multi-pipeline CI/CD setup powered by Drone CI on Kubernetes. This document describes the 5 specialized pipelines and how to use them. Проект NOCR использует современную многопайплайновую CI/CD систему на базе Drone CI, работающую на Kubernetes. Этот документ описывает 5 специализированных пайплайнов и способы их использования.
--- ---
## 🎯 Pipeline Architecture ## 🎯 Архитектура пайплайнов
### Pipeline 1: **Feature Validation** ### Пайплайн 1: **Feature Validation (Валидация функциональных веток)**
**Trigger:** Push to `feature/*` or `fix/*` branches **Триггер:** Push в ветки `feature/*`, `fix/*` или `issues/*`
**Purpose:** Fast feedback for developers **Назначение:** Быстрая обратная связь для разработчиков
**Duration:** ~3-5 minutes **Длительность:** ~3-5 минут
**What it does:** **Что делает:**
- Clones repo with submodules - Клонирует репозиторий с субмодулями
- Restores all NuGet packages (shared cache) - Восстанавливает все NuGet-пакеты (общий кэш)
- Builds all 4 services in Release mode - Собирает все 4 сервиса в Debug-режиме
- Runs unit and integration tests with Testcontainers - Запускает unit и integration тесты с Testcontainers
**Example workflow:** **Пример рабочего процесса:**
```bash ```bash
git checkout -b feature/add-new-filter git checkout -b feature/add-new-filter
# Make changes... # Внесите изменения...
git add . git add .
git commit -m "Add new filter functionality" git commit -m "Add new filter functionality"
git push origin feature/add-new-filter git push origin feature/add-new-filter
``` ```
Drone automatically runs tests. Check results before creating PR. Drone автоматически запустит тесты. Проверьте результаты перед созданием PR.
--- ---
### Pipeline 2: **Main Validation** ### Пайплайн 2: **Main Validation (Валидация основной ветки)**
**Trigger:** Push to `main` branch **Триггер:** Push в ветку `main`
**Purpose:** Validate main branch after merge **Назначение:** Валидация основной ветки после мерджа
**Duration:** ~3-5 minutes **Длительность:** ~3-5 минут
**What it does:** **Что делает:**
- Same as Feature Validation - То же, что и Feature Validation
- Ensures main branch is always in working state - Гарантирует, что ветка main всегда в рабочем состоянии
**Example workflow:** **Пример рабочего процесса:**
```bash ```bash
# After PR is merged to main # После мерджа PR в main
# Pipeline runs automatically # Пайплайн запускается автоматически
``` ```
--- ---
### Pipeline 3: **Contracts-Only Publish** ### Пайплайн 3: **Contracts-Only Publish (Публикация только контрактов)**
**Trigger:** Tag with commit message containing `contracts_only:<service>` **Триггер:** Тег с сообщением коммита, содержащим `contracts_only:<service>`
**Purpose:** Fast publish of contract packages without building images **Назначение:** Быстрая публикация NuGet-пакетов контрактов без сборки Docker-образов
**Duration:** ~2 minutes **Длительность:** ~2 минуты
**What it does:** **Что делает:**
- Packs specified service contracts into NuGet packages - Упаковывает контракты указанного сервиса в NuGet-пакеты
- Publishes to internal NuGet feed - Публикует во внутреннем NuGet-фиде
- Skips Docker image builds - Пропускает сборку Docker-образов
**Example workflow:** **Пример рабочего процесса:**
```bash ```bash
# Update telegram-listener contracts # Обновите контракты telegram-listener
cd telegram-listener cd telegram-listener
# Make changes to Async.Api.Contracts... # Внесите изменения в Async.Api.Contracts...
git add . git add .
git commit -m "contracts_only:telegram_listener - Add MessageEdited event" git commit -m "contracts_only:telegram_listener - Add MessageEdited event"
git push origin main git push origin main
# Create tag # Создайте тег
git tag v1.2.4-contracts git tag v1.2.4-contracts
git push origin v1.2.4-contracts git push origin v1.2.4-contracts
``` ```
**Supported markers:** **Поддерживаемые маркеры:**
- `contracts_only:telegram_listener` - `contracts_only:telegram_listener`
- `contracts_only:text_matcher` - `contracts_only:text_matcher`
- `contracts_only:users` - `contracts_only:users`
--- ---
### Pipeline 4: **Full Release** ### Пайплайн 4: **Full Release (Полный релиз)**
**Trigger:** Tag on main WITHOUT `contracts_only` or `deploy_only` in commit message **Триггер:** Тег на main БЕЗ `contracts_only` или `deploy_only` в сообщении коммита
**Purpose:** Complete release cycle **Назначение:** Полный цикл релиза
**Duration:** ~8-10 minutes **Длительность:** ~8-10 минут
**What it does:** **Что делает:**
1. **Stage 1:** Publish all contracts to NuGet (parallel) 1. **Этап 1:** Публикация всех контрактов в NuGet (параллельно)
2. **Stage 2:** Build all Docker images with Kaniko (3 parallel streams) 2. **Этап 2:** Сборка всех Docker-образов с Kaniko (3 параллельных потока)
3. **Stage 3:** Deploy to Kubernetes (only for tags matching `v*`) 3. **Этап 3:** Деплой в Kubernetes (только для тегов, начинающихся с `v`)
**Example workflow:** **Пример рабочего процесса:**
```bash ```bash
# Ready to release # Готовы к релизу
git tag v1.3.0 git tag v1.3.0
git push origin v1.3.0 git push origin v1.3.0
# Drone will: # Drone выполнит:
# 1. Publish contracts # 1. Публикацию контрактов
# 2. Build images (tagged with v1.3.0, commit SHA, and latest) # 2. Сборку образов (с тегами v1.3.0, commit SHA, и latest)
# 3. Deploy to k8s (if tag starts with 'v') # 3. Деплой в k8s (если тег начинается с 'v')
``` ```
**Image tags created:** **Создаваемые теги образов:**
- `hub.musk.fun/k8s/nocr/telegram_listener:v1.3.0` - `hub.musk.fun/k8s/nocr/telegram_listener:v1.3.0`
- `hub.musk.fun/k8s/nocr/telegram_listener:abc1234` (commit SHA) - `hub.musk.fun/k8s/nocr/telegram_listener:abc1234` (commit SHA)
- `hub.musk.fun/k8s/nocr/telegram_listener:latest` - `hub.musk.fun/k8s/nocr/telegram_listener:latest`
--- ---
### Pipeline 5: **Deploy-Only** ### Пайплайн 5: **Deploy-Only (Только деплой)**
**Trigger:** Tag with commit message containing `deploy_only:` **Триггер:** Тег с сообщением коммита, содержащим `deploy_only:`
**Purpose:** Fast deploy of already-built images **Назначение:** Быстрый деплой уже собранных образов
**Duration:** ~1 minute **Длительность:** ~1 минута
**What it does:** **Что делает:**
- Skips building - Пропускает сборку
- Deploys specified images to Kubernetes - Деплоит указанные образы в Kubernetes
- Useful for rolling back or promoting existing images - Полезно для отката или продвижения существующих образов
**Example workflow:** **Пример рабочего процесса:**
```bash ```bash
# Deploy existing images # Деплой существующих образов
git commit --allow-empty -m "deploy_only: Deploy v1.2.9" git commit --allow-empty -m "deploy_only: Deploy v1.2.9"
git tag v1.2.9-deploy git tag v1.2.9-deploy
git push origin v1.2.9-deploy git push origin v1.2.9-deploy
@ -129,80 +129,80 @@ git push origin v1.2.9-deploy
--- ---
## 🛠️ Deployment Scripts ## 🛠️ Скрипты деплоя
All deployment scripts are located in `_deploy/scripts/`: Все скрипты деплоя находятся в `_deploy/scripts/`:
### `deploy.sh` ### `deploy.sh`
**Purpose:** Deploy services to Kubernetes **Назначение:** Деплой сервисов в Kubernetes
**Usage:** **Использование:**
```bash ```bash
./deploy.sh <tag> <commit-sha> ./deploy.sh <tag> <commit-sha>
./deploy.sh v1.3.0 abc1234 ./deploy.sh v1.3.0 abc1234
``` ```
**Features:** **Возможности:**
- Updates deployment manifests with new image tags - Обновляет deployment-манифесты новыми тегами образов
- Applies manifests to cluster - Применяет манифесты в кластер
- Waits for rollouts to complete with timeout - Ожидает завершения rollout с таймаутом
- Runs health checks after deployment - Запускает проверки здоровья после деплоя
- Shows pod status - Показывает статус подов
### `rollback.sh` ### `rollback.sh`
**Purpose:** Rollback deployments to previous version **Назначение:** Откат деплоев к предыдущей версии
**Usage:** **Использование:**
```bash ```bash
# Rollback single service # Откат одного сервиса
./rollback.sh telegram-listener ./rollback.sh telegram-listener
# Rollback all services # Откат всех сервисов
./rollback.sh all ./rollback.sh all
``` ```
**Features:** **Возможности:**
- Shows revision history - Показывает историю ревизий
- Performs kubectl rollout undo - Выполняет kubectl rollout undo
- Waits for rollback to complete - Ожидает завершения отката
- Runs health checks after rollback - Запускает проверки здоровья после отката
### `health-check.sh` ### `health-check.sh`
**Purpose:** Check health of all Nocr services **Назначение:** Проверка здоровья всех сервисов NOCR
**Usage:** **Использование:**
```bash ```bash
./health-check.sh ./health-check.sh
``` ```
**Checks:** **Проверяет:**
- Pod status (Running/Ready) - Статус подов (Running/Ready)
- Health endpoints (/health) - Health-эндпоинты (/health)
- Recent events for failed pods - Последние события для упавших подов
--- ---
## 📦 Optimizations ## 📦 Оптимизации
### Shared NuGet Cache ### Общий NuGet-кэш
All pipelines use a shared temp volume for NuGet packages: Все пайплайны используют общий временный volume для NuGet-пакетов:
- First `dotnet restore` downloads packages - Первый `dotnet restore` скачивает пакеты
- Subsequent builds reuse cached packages - Последующие сборки переиспользуют кэшированные пакеты
- **~60% faster** than individual restores per service - **~60% быстрее**, чем индивидуальное восстановление для каждого сервиса
### Parallel Execution ### Параллельное выполнение
- Contract publishing: 3 services in parallel - Публикация контрактов: 3 сервиса параллельно
- Docker builds: 3 parallel streams - Сборка Docker: 3 параллельных потока
- Independent operations never block each other - Независимые операции никогда не блокируют друг друга
### Kaniko Caching ### Кэширование Kaniko
All Kaniko builds use: Все сборки Kaniko используют:
- `--cache=true` - Layer caching enabled - `--cache=true` - Включено кэширование слоев
- `--cache-repo=hub.musk.fun/k8s/cache/*` - Shared cache repo - `--cache-repo=hub.musk.fun/k8s/cache/*` - Общий репозиторий кэша
- `--compressed-caching=true` - Faster cache transfer - `--compressed-caching=true` - Быстрая передача кэша
--- ---
## 🧪 Testcontainers Support ## 🧪 Поддержка Testcontainers
Feature and Main validation pipelines include Docker-in-Docker service for Testcontainers: Пайплайны валидации Feature и Main включают Docker-in-Docker сервис для Testcontainers:
```yaml ```yaml
services: services:
@ -211,91 +211,149 @@ services:
privileged: true privileged: true
``` ```
Tests can use Testcontainers to spin up real databases, message queues, etc. Тесты могут использовать Testcontainers для запуска реальных баз данных, очередей сообщений и т.д.
--- ---
## 🔒 Required Secrets ## 🔒 Необходимые секреты
Configure these in Drone: Настройте эти секреты в Drone:
- `hub_username` - Docker registry username - `hub_username` - Имя пользователя Docker registry
- `hub_password` - Docker registry password - `hub_password` - Пароль Docker registry
- `nuget_musk_api_key` - NuGet feed API key - `nuget_musk_api_key` - API-ключ NuGet-фида
--- ---
## 📊 Pipeline Decision Tree ## 📊 Дерево решений пайплайна
``` ```
Push to feature/* → Feature Validation (build + test) Push в feature/* → Feature Validation (сборка + тесты)
Push to main → Main Validation (build + test) Push в main → Main Validation (сборка + тесты)
Tag + "contracts_only:" → Contracts Publish Тег + "contracts_only:" → Contracts Publish
Tag + "deploy_only:" → Deploy Only Тег + "deploy_only:" → Deploy Only
Tag (no markers) → Full Release (contracts → images → deploy) Тег (без маркеров) → Full Release (контракты → образы → деплой)
``` ```
--- ---
## 🎓 Best Practices ## 🎓 Лучшие практики
1. **Feature Branches** 1. **Функциональные ветки**
- Always create feature branches for new work - Всегда создавайте функциональные ветки для новой работы
- Let CI validate before merging to main - Дайте CI валидировать перед мерджем в main
2. **Contracts Changes** 2. **Изменения контрактов**
- Use `contracts_only:` for quick contract updates - Используйте `contracts_only:` для быстрого обновления контрактов
- Other services can update references immediately - Другие сервисы могут сразу обновить ссылки
3. **Release Process** 3. **Процесс релиза**
- Tag only from main branch - Создавайте теги только из ветки main
- Use semantic versioning (v1.2.3) - Используйте семантическое версионирование (v1.2.3)
- Tags starting with `v` auto-deploy to k8s - Теги, начинающиеся с `v`, автоматически деплоятся в k8s
4. **Emergency Rollback** 4. **Экстренный откат**
```bash ```bash
# Quick rollback via deploy-only # Быстрый откат через deploy-only
git commit --allow-empty -m "deploy_only: Rollback to v1.2.8" git commit --allow-empty -m "deploy_only: Rollback to v1.2.8"
git tag v1.2.8-rollback git tag v1.2.8-rollback
git push origin v1.2.8-rollback git push origin v1.2.8-rollback
# Or use rollback script directly on the cluster # Или используйте скрипт отката напрямую в кластере
kubectl exec -it deploy-pod -- bash kubectl exec -it deploy-pod -- bash
cd /flea/_deploy/scripts cd /flea/_deploy/scripts
./rollback.sh all ./rollback.sh all
``` ```
5. **Monitoring Deployments** 5. **Мониторинг деплоев**
- Watch Drone UI for pipeline progress - Следите за UI Drone для прогресса пайплайна
- Check pod logs: `kubectl logs -f deployment/telegram-listener -n nocr` - Проверяйте логи подов: `kubectl logs -f deployment/telegram-listener -n nocr`
- Run health checks: `./_deploy/scripts/health-check.sh` - Запускайте проверки здоровья: `./_deploy/scripts/health-check.sh`
--- ---
## 🐛 Troubleshooting ## 🐛 Устранение неполадок
### Pipeline stuck on "Waiting for contracts" ### Пайплайн завис на "Waiting for contracts"
**Cause:** Contract publish failed **Причина:** Публикация контракта упала
**Solution:** Check NuGet feed, verify API key **Решение:** Проверьте NuGet-фид, проверьте API-ключ
### Docker build fails with "unauthorized" ### Сборка Docker падает с ошибкой "unauthorized"
**Cause:** Invalid registry credentials **Причина:** Неверные учетные данные registry
**Solution:** Update `hub_username` and `hub_password` secrets **Решение:** Обновите секреты `hub_username` и `hub_password`
### Tests fail with "Cannot connect to Docker daemon" ### Тесты падают с ошибкой "Cannot connect to Docker daemon"
**Cause:** Testcontainers can't reach Docker-in-Docker service **Причина:** Testcontainers не может достичь Docker-in-Docker сервиса
**Solution:** Check `DOCKER_HOST` environment variable is set correctly **Решение:** Проверьте, что переменная окружения `DOCKER_HOST` установлена правильно
### Deployment fails with "ImagePullBackOff" ### Деплой падает с ошибкой "ImagePullBackOff"
**Cause:** Image not found in registry **Причина:** Образ не найден в registry
**Solution:** Verify image was built and pushed successfully in previous step **Решение:** Проверьте, что образ был собран и запушен успешно на предыдущем этапе
### YAML-ошибки в .drone.yml
**Причина:** Неправильное форматирование многострочных команд или двоеточие в переменных
**Решение:**
- Используйте блоки `|` для многострочных команд
- Экранируйте переменные с двоеточиями (например, `"${VAR:0:7}"`)
- Проверьте YAML: `python3 -c "import yaml; list(yaml.safe_load_all(open('.drone.yml')))"`
--- ---
## 📚 Additional Resources ## 📚 Дополнительные ресурсы
- [Drone CI Documentation](https://docs.drone.io/) - [Документация Drone CI](https://docs.drone.io/)
- [Kaniko Documentation](https://github.com/GoogleContainerTools/kaniko) - [Документация Kaniko](https://github.com/GoogleContainerTools/kaniko)
- [Testcontainers for .NET](https://dotnet.testcontainers.org/) - [Testcontainers для .NET](https://dotnet.testcontainers.org/)
- [Kubernetes Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - [Kubernetes Deployments](https://kubernetes.io/ru/docs/concepts/workloads/controllers/deployment/)
---
## 🔄 История изменений (15-16 октября 2025)
### Исправлена критическая проблема с YAML
**Проблема:**
- Ошибка `yaml: line 126: mapping values are not allowed in this context`
- Многострочные команды `/kaniko/executor` содержали переменные с двоеточием (`${DRONE_COMMIT_SHA:0:7}`)
- YAML парсер интерпретировал двоеточие как разделитель ключ:значение
**Решение:**
1. Обернули все команды `/kaniko/executor` в многострочные блоки с `|`
2. Добавили обратные слэши `\` для продолжения команды
3. Экранировали аргументы с двоеточиями в кавычках
**Пример:**
```yaml
# До (неправильно):
commands:
- /kaniko/executor
--destination=hub.musk.fun/image:${DRONE_COMMIT_SHA:0:7}
# После (правильно):
commands:
- |
/kaniko/executor \
--destination=hub.musk.fun/image:${DRONE_COMMIT_SHA:0:7}
```
### Добавлены новые функции
- ✨ Контракты-только пайплайн для быстрой итерации
- 🚀 Деплой-только пайплайн для откатов
- 🔄 Обработка MessageEdited событий
- 📝 Скрипт автокоммита субмодулей
- ⚡ Оптимизированный общий NuGet-кэш
- 🔧 Параллельная сборка и деплой
---
## 📞 Поддержка
Если у вас возникли проблемы с CI/CD:
1. Проверьте логи в Drone UI: https://drone.musk.fun/nocr/flea
2. Проверьте статус подов: `kubectl get pods -n nocr`
3. Запустите health-check: `./health-check.sh`
4. Проверьте логи контейнеров: `kubectl logs -f <pod-name> -n nocr`
Для вопросов по инфраструктуре обращайтесь к DevOps-команде.

View File

@ -1,47 +1,389 @@
# Архитектура системы NOCR
Диаграмма взаимодействия между сервисами системы мониторинга Telegram-каналов.
```mermaid ```mermaid
classDiagram classDiagram
TelegramListener <|-- Bus TelegramListener --|> Bus : publishes
TextMatcher <|-- TelegramClient Bus --|> TextMatcher : subscribes
TextMatcher <|-- Bus TextMatcher --|> Bus : publishes
Bus <|-- TextMatcher Bus --|> TelegramClient : subscribes
TelegramClient <|-- Bus TelegramClient --|> Users : REST API
Users <|-- TelegramClient TelegramClient --|> TextMatcher : REST API
Bus <|-- TelegramListener
class Bus{ class Bus{
+2024-03-28 18:27:50.551 [info] Installing honnef.co/go/tools/cmd/staticcheck@latest (/Users/nazarovsa/go/bin/staticcheck) SUCCEEDED <<RabbitMQ Message Broker>>
+MessageReceived events
+MessageEdited events
+TextSubscriptionMatched events
+TextSubscriptionUpdated events
} }
class TelegramListener { class TelegramListener {
+MessageReceived <<Сканер каналов>>
-TextMatcher.TextMatchCreated +publishes: MessageReceived
+publishes: MessageEdited
---
WTelegramClient (MTProto API)
Хранение сессий пользователей
} }
class TextMatcher { class TextMatcher {
+TextMatchCreated <<Обработчик совпадений>>
+TextMatchMatched +publishes: TextSubscriptionMatched
-TelegramListener.MessageReceived +publishes: TextSubscriptionUpdated
+long Create(CreateTextMatchRequest request) -subscribes: MessageReceived
-subscribes: MessageEdited
---
REST API:
+long Create(CreateTextMatchRequest)
+TextMatchData? GetById(long id) +TextMatchData? GetById(long id)
+TextMatchData[] GetByUserId(long userId) +TextMatchData[] GetByUserId(long userId)
+void Delete(long id) +void Delete(long id)
+void Activate(long id) +void Activate(long id)
+void Disable(long id) +void Disable(long id)
---
БД: История совпадений (MariaDB)
Проверка регулярных выражений
} }
class Users { class Users {
+long Create(CreateUserRequest request) <<Управление пользователями>>
---
REST API:
+long Create(CreateUserRequest)
+UserData? GetById(long id) +UserData? GetById(long id)
+UserData? GetByIdentity(UserIdentityType identityType, string identity) +UserData? GetByIdentity(type, identity)
---
БД: Пользователи и настройки (MariaDB)
} }
class TelegramClient { class TelegramClient {
-TextMatcher.TextMatchMatched <<Telegram Bot интерфейс>>
-subscribes: TextSubscriptionMatched
-subscribes: TextSubscriptionUpdated
---
Telegram.Bot (Bot API)
Обработка команд пользователей
Отправка уведомлений
---
REST клиенты:
-Users.Create() -Users.Create()
-Users.GetById() -Users.GetById()
-Users.GetByIdentity() -Users.GetByIdentity()
-TextMatcher.GetByUserId() -TextMatcher.GetByUserId()
-TextMatcher.Create() -TextMatcher.Create()
} }
```
## Описание компонентов
### 1. TelegramListener (Сканер каналов)
**Технологии:** .NET 8, WTelegramClient, Rebus
**Ответственность:**
- Подключение к Telegram через MTProto API
- Подписка на открытые каналы и чаты
- Получение новых и отредактированных сообщений
- Публикация событий в RabbitMQ
**Публикуемые события:**
- `MessageReceived` - новое сообщение получено
- `MessageEdited` - сообщение отредактировано
**Примечание:** WTelegram отправляет оба события (`UpdateNewChannelMessage` и `UpdateEditChannelMessage`) для одного и того же сообщения. TelegramListener публикует отдельные события, чтобы избежать дублирования уведомлений.
---
### 2. TextMatcher (Обработчик совпадений)
**Технологии:** .NET 8, Entity Framework Core, MariaDB, Rebus
**Ответственность:**
- Подписка на события сообщений от TelegramListener
- Проверка совпадений с пользовательскими подписками (regex, ключевые слова)
- Хранение истории совпадений в БД
- Публикация событий о найденных совпадениях
- REST API для управления подписками
**Подписывается на события:**
- `MessageReceived` - проверка нового сообщения
- `MessageEdited` - обновление ранее найденного совпадения
**Публикуемые события:**
- `TextSubscriptionMatched` - новое совпадение найдено
- `TextSubscriptionUpdated` - обновление ранее найденного совпадения
**REST API эндпоинты:**
- `POST /api/textmatch` - Создать новую подписку
- `GET /api/textmatch/{id}` - Получить подписку по ID
- `GET /api/textmatch/user/{userId}` - Получить все подписки пользователя
- `DELETE /api/textmatch/{id}` - Удалить подписку
- `POST /api/textmatch/{id}/activate` - Активировать подписку
- `POST /api/textmatch/{id}/disable` - Отключить подписку
---
### 3. TelegramClient (Telegram Bot)
**Технологии:** .NET 8, Telegram.Bot, Rebus, RestEase
**Ответственность:**
- Интерфейс бота для взаимодействия с пользователями
- Обработка команд бота (/start, /subscribe, /list и т.д.)
- Подписка на события совпадений
- Отправка уведомлений пользователям
- Интеграция с Users и TextMatcher через REST API
**Подписывается на события:**
- `TextSubscriptionMatched` - отправка уведомления о новом совпадении
- `TextSubscriptionUpdated` - уведомление об обновлении
**REST клиенты:**
- **Users API:** управление пользователями
- **TextMatcher API:** управление подписками
---
### 4. Users (Управление пользователями)
**Технологии:** .NET 8, Entity Framework Core, MariaDB
**Ответственность:**
- CRUD операции для пользователей
- Хранение предпочтений и настроек
- REST API для других сервисов
**REST API эндпоинты:**
- `POST /api/users` - Создать нового пользователя
- `GET /api/users/{id}` - Получить пользователя по ID
- `GET /api/users/identity/{type}/{identity}` - Найти пользователя по Telegram ID
---
### 5. RabbitMQ (Message Bus)
**Технологии:** RabbitMQ 3.x, Rebus
**Ответственность:**
- Асинхронная доставка событий между сервисами
- Гарантия доставки сообщений
- Очереди и обмены (exchanges)
**Настройка:**
- **Direct Exchange:** `nocr.direct` - для точечной маршрутизации
- **Topic Exchange:** `nocr.topics` - для публикации/подписки по топикам
- **Очереди:** Каждый сервис имеет свою input queue
---
## Паттерны взаимодействия
### Event-Driven Architecture (Асинхронная)
```
TelegramListener → RabbitMQ → TextMatcher → RabbitMQ → TelegramClient
```
**Преимущества:**
- Слабая связанность сервисов
- Масштабируемость (можно добавить несколько обработчиков)
- Отказоустойчивость (сообщения не теряются при падении сервиса)
### Request-Response (Синхронная)
```
TelegramClient → REST API → Users
TelegramClient → REST API → TextMatcher
```
**Использование:**
- Создание/получение данных пользователей
- Управление подписками
- Запросы, требующие немедленного ответа
---
## Потоки данных
### Основной поток (Мониторинг и уведомления)
1. **Сканирование:**
- TelegramListener подключается к Telegram MTProto
- Получает новые сообщения из каналов
- Публикует `MessageReceived` в RabbitMQ
2. **Обработка:**
- TextMatcher получает `MessageReceived`
- Проверяет сообщение на совпадение с подписками
- Сохраняет историю в БД
- Публикует `TextSubscriptionMatched` в RabbitMQ
3. **Уведомление:**
- TelegramClient получает `TextSubscriptionMatched`
- Получает данные пользователя из Users API
- Отправляет уведомление через Telegram Bot API
### Поток редактирования сообщений
1. **Обновление:**
- TelegramListener получает `UpdateEditChannelMessage`
- Публикует `MessageEdited` в RabbitMQ
2. **Повторная проверка:**
- TextMatcher получает `MessageEdited`
- Проверяет, было ли это сообщение ранее найдено
- Если было, публикует `TextSubscriptionUpdated`
3. **Уведомление об обновлении:**
- TelegramClient получает `TextSubscriptionUpdated`
- Отправляет обновленное уведомление пользователю
---
## Clean Architecture
Каждый сервис следует принципам Clean Architecture:
``` ```
┌─────────────────────────────────────────┐
│ Host (API / Entry Point) │ ← ASP.NET Core, Controllers
├─────────────────────────────────────────┤
│ AppServices (Business Logic) │ ← Use Cases, Handlers
├─────────────────────────────────────────┤
│ Core (Domain / Shared) │ ← Entities, Interfaces
├─────────────────────────────────────────┤
│ Persistence (Data Access) │ ← EF Core, Repositories
├─────────────────────────────────────────┤
│ Async.Api.Contracts (Event Contracts) │ ← RabbitMQ Events (NuGet)
├─────────────────────────────────────────┤
│ Api.Contracts (REST Contracts) │ ← DTOs, Requests (NuGet)
├─────────────────────────────────────────┤
│ Migrator (Database Migrations) │ ← EF Core Migrations
└─────────────────────────────────────────┘
```
**Преимущества:**
- Независимость от фреймворков
- Тестируемость
- Независимость от UI/Database
- Переиспользование контрактов через NuGet
---
## Базы данных
### TextMatcher Database (MariaDB)
**Порт:** 3316 (локально), 3306 (Docker/K8s)
**Таблицы:**
- `TextMatches` - Пользовательские подписки
- `MatchHistory` - История найденных совпадений
- `__EFMigrationsHistory` - История миграций EF Core
### Users Database (MariaDB)
**Порт:** 3326 (локально), 3306 (Docker/K8s)
**Таблицы:**
- `Users` - Пользователи системы
- `UserPreferences` - Настройки пользователей
- `__EFMigrationsHistory` - История миграций EF Core
---
## Развертывание
### Docker Compose (Локальная разработка)
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ telegram- │ │ telegram- │ │ text- │ │ users │
│ listener │ │ client │ │ matcher │ │ │
│ :5040 │ │ :5050 │ │ :5041 │ │ :5042 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │ │
└────────────────┴────────────────┴────────────────┘
┌─────────┴─────────┐
│ RabbitMQ │
│ :5672, :15672 │
└───────────────────┘
┌───────────────┴───────────────┐
│ │
┌───────┴────────┐ ┌────────┴────────┐
│ text-matcher- │ │ users-db │
│ db :3316 │ │ :3326 │
└────────────────┘ └─────────────────┘
```
### Kubernetes (Production)
- **Namespace:** nocr
- **Services:** ClusterIP для внутренней коммуникации
- **Deployments:** С health checks и resource limits
- **Secrets:** Для Telegram API credentials и Bot tokens
- **ConfigMaps:** Для конфигурации окружения
---
## Мониторинг и наблюдаемость
### Health Checks
Каждый сервис предоставляет `/health` эндпоинт:
- **telegram-listener:** http://localhost:5040/health
- **text-matcher:** http://localhost:5041/health
- **users:** http://localhost:5042/health
- **telegram-client:** http://localhost:5050/health
### Логирование
- Структурированное логирование через Serilog
- Логи выводятся в stdout для Docker/K8s
- Централизованное логирование через kubectl logs
### Метрики
- RabbitMQ Management UI: http://localhost:15672
- Мониторинг очередей и exchanges
- Просмотр активных подключений
---
## Масштабирование
### Горизонтальное масштабирование
**Можно масштабировать:**
- ✅ **TextMatcher** - несколько инстансов обрабатывают сообщения параллельно
- ✅ **TelegramClient** - несколько инстансов отправляют уведомления параллельно
- ✅ **Users** - stateless API, можно масштабировать без ограничений
**Ограничения:**
- ⚠️ **TelegramListener** - один инстанс на одну Telegram сессию (ограничение WTelegram)
### Вертикальное масштабирование
- Увеличение CPU/RAM для сервисов
- Оптимизация запросов к БД
- Настройка connection pools
---
## Безопасность
### Секреты
- Telegram API credentials хранятся в K8s Secrets
- Bot tokens хранятся в K8s Secrets
- Database credentials в environment variables
### Сетевая безопасность
- Все сервисы работают в приватной сети
- Только TelegramClient имеет доступ к внешним API
- RabbitMQ защищен credentials
### Валидация
- Входящие данные валидируются в AppServices
- REST API использует Data Annotations
- Event contracts строго типизированы
---
## Дополнительная информация
- **[README.md](README.md)** - Общая документация проекта
- **[CONFIGURATION.md](CONFIGURATION.md)** - Руководство по конфигурации
- **[_deploy/README.md](_deploy/README.md)** - CI/CD и деплой
- **[CLAUDE.md](CLAUDE.md)** - Инструкции для AI-ассистента
---
оследнее обновление: 16 октября 2025_