Обновил документацию.
This commit is contained in:
parent
32b0253981
commit
15519f2377
348
CONFIGURATION.md
348
CONFIGURATION.md
@ -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)
|
||||
2. [Deployment Scenarios](#deployment-scenarios)
|
||||
- [Local Development (VS Code)](#local-development-vs-code)
|
||||
1. [Обзор системы конфигурации](#обзор-системы-конфигурации)
|
||||
2. [Сценарии развертывания](#сценарии-развертывания)
|
||||
- [Локальная разработка (VS Code)](#локальная-разработка-vs-code)
|
||||
- [Docker Compose](#docker-compose)
|
||||
- [Kubernetes](#kubernetes)
|
||||
3. [Configuration Priority](#configuration-priority)
|
||||
4. [Service-Specific Settings](#service-specific-settings)
|
||||
5. [Debug Mode](#debug-mode)
|
||||
6. [Troubleshooting](#troubleshooting)
|
||||
3. [Приоритет конфигурации](#приоритет-конфигурации)
|
||||
4. [Настройки для конкретных сервисов](#настройки-для-конкретных-сервисов)
|
||||
5. [Режим отладки](#режим-отладки)
|
||||
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)
|
||||
2. `appsettings.{Environment}.json` - Environment-specific settings (some committed, some not)
|
||||
3. User Secrets - Development-only secrets (stored locally, not in git)
|
||||
4. **Environment Variables** - **Highest priority** (overrides everything)
|
||||
1. `appsettings.json` - Базовая конфигурация (коммитится в git)
|
||||
2. `appsettings.{Environment}.json` - Настройки для конкретного окружения (некоторые коммитятся, некоторые нет)
|
||||
3. User Secrets - Секреты только для разработки (хранятся локально, не в git)
|
||||
4. **Переменные окружения** - **Наивысший приоритет** (переопределяют всё)
|
||||
|
||||
### Important Notes
|
||||
### Важные примечания
|
||||
|
||||
- **Never commit secrets to git**
|
||||
- Use `.example` files as templates
|
||||
- Environment Variables always win in priority
|
||||
- Each service has its own configuration requirements
|
||||
- **Никогда не коммитьте секреты в git**
|
||||
- Используйте файлы `.example` как шаблоны
|
||||
- Переменные окружения всегда имеют наивысший приоритет
|
||||
- Каждый сервис имеет свои требования к конфигурации
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
# Telegram Listener
|
||||
@ -62,11 +62,11 @@ cd telegram-client/src/Nocr.TelegramClient.Host
|
||||
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
|
||||
{
|
||||
"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
|
||||
{
|
||||
"name": "Launch Service",
|
||||
"name": "Запуск сервиса",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"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
|
||||
# Start only infrastructure services
|
||||
# Запустить только инфраструктурные сервисы
|
||||
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
|
||||
|
||||
For running the entire system locally with Docker:
|
||||
Для запуска всей системы локально с Docker:
|
||||
|
||||
#### Step 1: Create .nocr.env File
|
||||
#### Шаг 1: Создание файла .nocr.env
|
||||
|
||||
```bash
|
||||
cd /path/to/project/root
|
||||
cd /путь/к/корню/проекта
|
||||
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
|
||||
# Telegram Listener - get from https://my.telegram.org/apps
|
||||
# Telegram Listener - получить на https://my.telegram.org/apps
|
||||
WTelegramClientOptions__ApiId=22101230
|
||||
WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b
|
||||
WTelegramClientOptions__PhoneNumber=79167310711
|
||||
|
||||
# Telegram Client Bot - get from @BotFather
|
||||
# Telegram Client Bot - получить у @BotFather
|
||||
TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz
|
||||
|
||||
# Optional: Enable debug logging
|
||||
# Опционально: включить отладочное логирование
|
||||
# NOCR_DEBUG_MODE=true
|
||||
```
|
||||
|
||||
#### Step 3: Create DockerCompose Configuration Files
|
||||
#### Шаг 3: Создание конфигурационных файлов для DockerCompose
|
||||
|
||||
Each service needs `appsettings.DockerCompose.json`:
|
||||
Каждому сервису нужен `appsettings.DockerCompose.json`:
|
||||
|
||||
```bash
|
||||
# For each service
|
||||
# Для каждого сервиса
|
||||
cd telegram-listener/src/Nocr.TelegramListener.Host
|
||||
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
|
||||
```
|
||||
|
||||
**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
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
Or build and start:
|
||||
Или со сборкой:
|
||||
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
#### Step 5: Verify Services are Running
|
||||
#### Шаг 5: Проверка работоспособности сервисов
|
||||
|
||||
- Telegram Listener: http://localhost:5040/health
|
||||
- Text Matcher: http://localhost:5041/health
|
||||
@ -189,32 +189,32 @@ docker-compose up --build
|
||||
|
||||
### 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
|
||||
# Create namespace
|
||||
# Создать namespace
|
||||
kubectl create namespace nocr
|
||||
|
||||
# Create secrets for Telegram Listener
|
||||
# Создать secrets для Telegram Listener
|
||||
kubectl create secret generic telegram-listener-secrets \
|
||||
--from-literal=WTelegramClientOptions__ApiId=22101230 \
|
||||
--from-literal=WTelegramClientOptions__ApiHash=c72f884d8eb84cb7134a14362bff060b \
|
||||
--from-literal=WTelegramClientOptions__PhoneNumber=79167310711 \
|
||||
-n nocr
|
||||
|
||||
# Create secrets for Telegram Client
|
||||
# Создать secrets для Telegram Client
|
||||
kubectl create secret generic telegram-client-secrets \
|
||||
--from-literal=TelegramBotOptions__Token=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz \
|
||||
-n nocr
|
||||
```
|
||||
|
||||
#### Step 2: Reference Secrets in Deployment
|
||||
#### Шаг 2: Ссылка на Secrets в Deployment
|
||||
|
||||
Example Kubernetes deployment manifest:
|
||||
Пример манифеста Kubernetes deployment:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
@ -236,9 +236,9 @@ spec:
|
||||
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
|
||||
{
|
||||
@ -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
|
||||
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)
|
||||
2. ⬆️ `appsettings.{Environment}.json` (e.g., Development, DockerCompose, Production)
|
||||
3. ⬆️ User Secrets (Development only)
|
||||
4. ⬆️⬆️ **Environment Variables (ALWAYS WINS)**
|
||||
1. ⬇️ `appsettings.json` (базовый)
|
||||
2. ⬆️ `appsettings.{Environment}.json` (например, Development, DockerCompose, Production)
|
||||
3. ⬆️ User Secrets (только Development)
|
||||
4. ⬆️⬆️ **Переменные окружения (ВСЕГДА ВЫИГРЫВАЮТ)**
|
||||
|
||||
### Example Scenario
|
||||
### Пример сценария
|
||||
|
||||
If you have:
|
||||
Если у вас есть:
|
||||
|
||||
- `appsettings.json`: `"ConnectionString": ""`
|
||||
- `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
|
||||
|
||||
**Required Configuration:**
|
||||
**Обязательная конфигурация:**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -302,17 +302,17 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
|
||||
}
|
||||
```
|
||||
|
||||
**How to obtain Telegram credentials:**
|
||||
1. Visit https://my.telegram.org/apps
|
||||
2. Log in with your phone number
|
||||
3. Create a new application
|
||||
4. Copy `api_id` and `api_hash`
|
||||
**Как получить учетные данные Telegram:**
|
||||
1. Посетите https://my.telegram.org/apps
|
||||
2. Войдите с вашим номером телефона
|
||||
3. Создайте новое приложение
|
||||
4. Скопируйте `api_id` и `api_hash`
|
||||
|
||||
---
|
||||
|
||||
### Text Matcher
|
||||
|
||||
**Required Configuration:**
|
||||
**Обязательная конфигурация:**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -325,7 +325,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
|
||||
}
|
||||
```
|
||||
|
||||
**Ports by environment:**
|
||||
**Порты по окружениям:**
|
||||
- Development: `localhost:3316`
|
||||
- Docker Compose: `nocr-text-matcher-db: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
|
||||
|
||||
**Required Configuration:**
|
||||
**Обязательная конфигурация:**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -344,7 +344,7 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
|
||||
}
|
||||
```
|
||||
|
||||
**Ports by environment:**
|
||||
**Порты по окружениям:**
|
||||
- Development: `localhost:3326`
|
||||
- Docker Compose: `nocr-users-db: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
|
||||
|
||||
**Required Configuration:**
|
||||
**Обязательная конфигурация:**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -372,45 +372,45 @@ This is why we removed `appsettings.protected.json` - it was overriding Docker C
|
||||
}
|
||||
```
|
||||
|
||||
**How to obtain Bot Token:**
|
||||
1. Open Telegram and find @BotFather
|
||||
2. Send `/newbot` command
|
||||
3. Follow instructions to create your bot
|
||||
4. Copy the token provided
|
||||
**Как получить Bot Token:**
|
||||
1. Откройте Telegram и найдите @BotFather
|
||||
2. Отправьте команду `/newbot`
|
||||
3. Следуйте инструкциям для создания вашего бота
|
||||
4. Скопируйте предоставленный токен
|
||||
|
||||
---
|
||||
|
||||
## Debug Mode
|
||||
## Режим отладки
|
||||
|
||||
Enable debug mode to print masked configuration values on startup.
|
||||
Включите режим отладки для вывода маскированных значений конфигурации при запуске.
|
||||
|
||||
### How to Enable
|
||||
### Как включить
|
||||
|
||||
Set environment variable:
|
||||
Установите переменную окружения:
|
||||
|
||||
```bash
|
||||
export NOCR_DEBUG_MODE=true
|
||||
```
|
||||
|
||||
Or in `.nocr.env`:
|
||||
Или в `.nocr.env`:
|
||||
|
||||
```bash
|
||||
NOCR_DEBUG_MODE=true
|
||||
```
|
||||
|
||||
Or in `docker-compose.yml`:
|
||||
Или в `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
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] ConnectionString: amqp://admin:***@nocr-rabbitmq:5672/
|
||||
[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] ApiHash: c7...0b
|
||||
[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
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Check if RabbitMQ is running: `docker-compose ps nocr-rabbitmq`
|
||||
2. Enable debug mode: `NOCR_DEBUG_MODE=true`
|
||||
3. Verify ConnectionString in debug output
|
||||
4. For Docker Compose, ensure hostname is `nocr-rabbitmq:5672`, NOT `localhost:5672`
|
||||
5. Check if environment variable is overriding appsettings
|
||||
**Решение:**
|
||||
1. Проверьте, работает ли RabbitMQ: `docker-compose ps nocr-rabbitmq`
|
||||
2. Включите режим отладки: `NOCR_DEBUG_MODE=true`
|
||||
3. Проверьте ConnectionString в выводе отладки
|
||||
4. Для Docker Compose убедитесь, что hostname - `nocr-rabbitmq:5672`, НЕ `localhost:5672`
|
||||
5. Проверьте, не переопределяет ли переменная окружения appsettings
|
||||
|
||||
---
|
||||
|
||||
### Problem: Service can't connect to database
|
||||
### Проблема: Сервис не может подключиться к базе данных
|
||||
|
||||
**Symptoms:**
|
||||
**Симптомы:**
|
||||
```
|
||||
Unable to connect to any of the specified MySQL hosts
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
1. Check database is running: `docker-compose ps nocr-text-matcher-db`
|
||||
2. Enable debug mode to see masked connection string
|
||||
3. Verify hostname in connection string:
|
||||
**Решение:**
|
||||
1. Проверьте, что база данных запущена: `docker-compose ps nocr-text-matcher-db`
|
||||
2. Включите режим отладки для просмотра маскированной строки подключения
|
||||
3. Проверьте hostname в строке подключения:
|
||||
- Docker Compose: `nocr-text-matcher-db:3306`
|
||||
- Local dev: `localhost:3316`
|
||||
4. Wait for database healthcheck to pass (may take 10-30 seconds on first start)
|
||||
- Локальная разработка: `localhost:3316`
|
||||
4. Подождите прохождения healthcheck (может занять 10-30 секунд при первом запуске)
|
||||
|
||||
---
|
||||
|
||||
### Problem: Configuration values not applied
|
||||
### Проблема: Значения конфигурации не применяются
|
||||
|
||||
**Symptoms:**
|
||||
- Settings in `appsettings.Development.json` are ignored
|
||||
- Service uses wrong configuration
|
||||
**Симптомы:**
|
||||
- Настройки в `appsettings.Development.json` игнорируются
|
||||
- Сервис использует неправильную конфигурацию
|
||||
|
||||
**Solution:**
|
||||
1. Check `ASPNETCORE_ENVIRONMENT` is set correctly:
|
||||
**Решение:**
|
||||
1. Проверьте, что `ASPNETCORE_ENVIRONMENT` установлен правильно:
|
||||
- VS Code: `Development`
|
||||
- Docker Compose: `DockerCompose`
|
||||
- K8s: `Production`
|
||||
2. Enable debug mode to see which values are loaded
|
||||
3. Check for environment variables overriding your settings
|
||||
4. Remember: **Environment Variables always win!**
|
||||
2. Включите режим отладки для просмотра загруженных значений
|
||||
3. Проверьте переменные окружения, переопределяющие ваши настройки
|
||||
4. Помните: **Переменные окружения всегда выигрывают!**
|
||||
|
||||
---
|
||||
|
||||
### Problem: Secrets exposed in logs
|
||||
### Проблема: Секреты раскрыты в логах
|
||||
|
||||
**Solution:**
|
||||
- Debug mode automatically masks sensitive values
|
||||
- Never log configuration in production without masking
|
||||
- Review debug output format in `Startup.cs`:
|
||||
- Passwords: `amqp://user:***@host`
|
||||
- Secrets: `ab...yz` (first 2 + last 2 chars only)
|
||||
**Решение:**
|
||||
- Режим отладки автоматически маскирует конфиденциальные значения
|
||||
- Никогда не логируйте конфигурацию в production без маскировки
|
||||
- Проверьте формат вывода отладки в `Startup.cs`:
|
||||
- Пароли: `amqp://user:***@host`
|
||||
- Секреты: `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`
|
||||
2. Fill in your actual values
|
||||
3. Make sure `.nocr.env` is in the project root (same level as `docker-compose.yml`)
|
||||
**Решение:**
|
||||
1. Скопируйте файл-пример: `cp .nocr.env.example .nocr.env`
|
||||
2. Заполните ваши реальные значения
|
||||
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
|
||||
# JSON: { "Section": { "Key": "Value" } }
|
||||
# Environment Variable:
|
||||
# Переменная окружения:
|
||||
Section__Key=Value
|
||||
|
||||
# Example:
|
||||
# Примеры:
|
||||
WTelegramClientOptions__ApiId=12345
|
||||
RebusRabbitMqOptions__ConnectionString=amqp://localhost
|
||||
```
|
||||
|
||||
### File Locations
|
||||
### Расположение файлов
|
||||
|
||||
```
|
||||
flea/ # Project root
|
||||
├── .nocr.env # Your secrets (gitignored)
|
||||
├── .nocr.env.example # Template (committed)
|
||||
├── docker-compose.yml # References .nocr.env
|
||||
flea/ # Корень проекта
|
||||
├── .nocr.env # Ваши секреты (gitignored)
|
||||
├── .nocr.env.example # Шаблон (коммитится)
|
||||
├── docker-compose.yml # Ссылается на .nocr.env
|
||||
│
|
||||
├── telegram-listener/
|
||||
│ └── src/Nocr.TelegramListener.Host/
|
||||
│ ├── appsettings.json # Base (committed)
|
||||
│ ├── appsettings.Development.json # Local dev (gitignored)
|
||||
│ ├── appsettings.Development.json.example # Template (committed)
|
||||
│ ├── appsettings.json # Базовый (коммитится)
|
||||
│ ├── appsettings.Development.json # Локальная разработка (gitignored)
|
||||
│ ├── appsettings.Development.json.example # Шаблон (коммитится)
|
||||
│ ├── 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
|
||||
2. ✅ **Use environment variables** for sensitive data in production
|
||||
3. ✅ **Use K8s Secrets** for Kubernetes deployments
|
||||
4. ✅ **Enable debug mode** only when troubleshooting
|
||||
5. ✅ **Rotate credentials** regularly
|
||||
6. ✅ **Use User Secrets** for local development (optional)
|
||||
7. ❌ **Don't commit** `.nocr.env` or `appsettings.*.json` (except `.example` files)
|
||||
8. ❌ **Don't use** `appsettings.protected.json` (removed from code)
|
||||
1. ✅ **Никогда не коммитьте секреты** - используйте файлы `.example` как шаблоны
|
||||
2. ✅ **Используйте переменные окружения** для конфиденциальных данных в production
|
||||
3. ✅ **Используйте K8s Secrets** для развертывания в Kubernetes
|
||||
4. ✅ **Включайте режим отладки** только при устранении неполадок
|
||||
5. ✅ **Ротируйте учетные данные** регулярно
|
||||
6. ✅ **Используйте User Secrets** для локальной разработки (опционально)
|
||||
7. ❌ **Не коммитьте** `.nocr.env` или `appsettings.*.json` (кроме файлов `.example`)
|
||||
8. ❌ **Не используйте** `appsettings.protected.json` (удален из кода)
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
## Дополнительные ресурсы
|
||||
|
||||
- [ASP.NET Core Configuration Docs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/)
|
||||
- [Docker Compose Environment Variables](https://docs.docker.com/compose/environment-variables/)
|
||||
- [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
|
||||
- [Telegram API Documentation](https://core.telegram.org/api)
|
||||
- [Документация конфигурации ASP.NET Core](https://learn.microsoft.com/ru-ru/aspnet/core/fundamentals/configuration/)
|
||||
- [Переменные окружения Docker Compose](https://docs.docker.com/compose/environment-variables/)
|
||||
- [Kubernetes Secrets](https://kubernetes.io/ru/docs/concepts/configuration/secret/)
|
||||
- [Документация Telegram API](https://core.telegram.org/api)
|
||||
- [Telegram Bot API](https://core.telegram.org/bots/api)
|
||||
|
||||
450
README.md
450
README.md
@ -1,22 +1,446 @@
|
||||
# Спец проект для работы с зависимостями, внешними и внутренними сервисами и приложениями.
|
||||
# NOCR - Система мониторинга Telegram-каналов
|
||||
|
||||
Аккумуляция всех вложенных проектов.
|
||||
[](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:
|
||||
[](https://drone.musk.fun/nocr/flea)
|
||||
### Вариант 1: Docker Compose (рекомендуется)
|
||||
|
||||
```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)
|
||||
|
||||
@ -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**
|
||||
**Trigger:** Push to `feature/*` or `fix/*` branches
|
||||
**Purpose:** Fast feedback for developers
|
||||
**Duration:** ~3-5 minutes
|
||||
### Пайплайн 1: **Feature Validation (Валидация функциональных веток)**
|
||||
**Триггер:** Push в ветки `feature/*`, `fix/*` или `issues/*`
|
||||
**Назначение:** Быстрая обратная связь для разработчиков
|
||||
**Длительность:** ~3-5 минут
|
||||
|
||||
**What it does:**
|
||||
- Clones repo with submodules
|
||||
- Restores all NuGet packages (shared cache)
|
||||
- Builds all 4 services in Release mode
|
||||
- Runs unit and integration tests with Testcontainers
|
||||
**Что делает:**
|
||||
- Клонирует репозиторий с субмодулями
|
||||
- Восстанавливает все NuGet-пакеты (общий кэш)
|
||||
- Собирает все 4 сервиса в Debug-режиме
|
||||
- Запускает unit и integration тесты с Testcontainers
|
||||
|
||||
**Example workflow:**
|
||||
**Пример рабочего процесса:**
|
||||
```bash
|
||||
git checkout -b feature/add-new-filter
|
||||
# Make changes...
|
||||
# Внесите изменения...
|
||||
git add .
|
||||
git commit -m "Add new filter functionality"
|
||||
git push origin feature/add-new-filter
|
||||
```
|
||||
|
||||
Drone automatically runs tests. Check results before creating PR.
|
||||
Drone автоматически запустит тесты. Проверьте результаты перед созданием PR.
|
||||
|
||||
---
|
||||
|
||||
### Pipeline 2: **Main Validation**
|
||||
**Trigger:** Push to `main` branch
|
||||
**Purpose:** Validate main branch after merge
|
||||
**Duration:** ~3-5 minutes
|
||||
### Пайплайн 2: **Main Validation (Валидация основной ветки)**
|
||||
**Триггер:** Push в ветку `main`
|
||||
**Назначение:** Валидация основной ветки после мерджа
|
||||
**Длительность:** ~3-5 минут
|
||||
|
||||
**What it does:**
|
||||
- Same as Feature Validation
|
||||
- Ensures main branch is always in working state
|
||||
**Что делает:**
|
||||
- То же, что и Feature Validation
|
||||
- Гарантирует, что ветка main всегда в рабочем состоянии
|
||||
|
||||
**Example workflow:**
|
||||
**Пример рабочего процесса:**
|
||||
```bash
|
||||
# After PR is merged to main
|
||||
# Pipeline runs automatically
|
||||
# После мерджа PR в main
|
||||
# Пайплайн запускается автоматически
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pipeline 3: **Contracts-Only Publish**
|
||||
**Trigger:** Tag with commit message containing `contracts_only:<service>`
|
||||
**Purpose:** Fast publish of contract packages without building images
|
||||
**Duration:** ~2 minutes
|
||||
### Пайплайн 3: **Contracts-Only Publish (Публикация только контрактов)**
|
||||
**Триггер:** Тег с сообщением коммита, содержащим `contracts_only:<service>`
|
||||
**Назначение:** Быстрая публикация NuGet-пакетов контрактов без сборки Docker-образов
|
||||
**Длительность:** ~2 минуты
|
||||
|
||||
**What it does:**
|
||||
- Packs specified service contracts into NuGet packages
|
||||
- Publishes to internal NuGet feed
|
||||
- Skips Docker image builds
|
||||
**Что делает:**
|
||||
- Упаковывает контракты указанного сервиса в NuGet-пакеты
|
||||
- Публикует во внутреннем NuGet-фиде
|
||||
- Пропускает сборку Docker-образов
|
||||
|
||||
**Example workflow:**
|
||||
**Пример рабочего процесса:**
|
||||
```bash
|
||||
# Update telegram-listener contracts
|
||||
# Обновите контракты telegram-listener
|
||||
cd telegram-listener
|
||||
# Make changes to Async.Api.Contracts...
|
||||
# Внесите изменения в Async.Api.Contracts...
|
||||
git add .
|
||||
git commit -m "contracts_only:telegram_listener - Add MessageEdited event"
|
||||
git push origin main
|
||||
|
||||
# Create tag
|
||||
# Создайте тег
|
||||
git tag v1.2.4-contracts
|
||||
git push origin v1.2.4-contracts
|
||||
```
|
||||
|
||||
**Supported markers:**
|
||||
**Поддерживаемые маркеры:**
|
||||
- `contracts_only:telegram_listener`
|
||||
- `contracts_only:text_matcher`
|
||||
- `contracts_only:users`
|
||||
|
||||
---
|
||||
|
||||
### Pipeline 4: **Full Release**
|
||||
**Trigger:** Tag on main WITHOUT `contracts_only` or `deploy_only` in commit message
|
||||
**Purpose:** Complete release cycle
|
||||
**Duration:** ~8-10 minutes
|
||||
### Пайплайн 4: **Full Release (Полный релиз)**
|
||||
**Триггер:** Тег на main БЕЗ `contracts_only` или `deploy_only` в сообщении коммита
|
||||
**Назначение:** Полный цикл релиза
|
||||
**Длительность:** ~8-10 минут
|
||||
|
||||
**What it does:**
|
||||
1. **Stage 1:** Publish all contracts to NuGet (parallel)
|
||||
2. **Stage 2:** Build all Docker images with Kaniko (3 parallel streams)
|
||||
3. **Stage 3:** Deploy to Kubernetes (only for tags matching `v*`)
|
||||
**Что делает:**
|
||||
1. **Этап 1:** Публикация всех контрактов в NuGet (параллельно)
|
||||
2. **Этап 2:** Сборка всех Docker-образов с Kaniko (3 параллельных потока)
|
||||
3. **Этап 3:** Деплой в Kubernetes (только для тегов, начинающихся с `v`)
|
||||
|
||||
**Example workflow:**
|
||||
**Пример рабочего процесса:**
|
||||
```bash
|
||||
# Ready to release
|
||||
# Готовы к релизу
|
||||
git tag v1.3.0
|
||||
git push origin v1.3.0
|
||||
|
||||
# Drone will:
|
||||
# 1. Publish contracts
|
||||
# 2. Build images (tagged with v1.3.0, commit SHA, and latest)
|
||||
# 3. Deploy to k8s (if tag starts with 'v')
|
||||
# Drone выполнит:
|
||||
# 1. Публикацию контрактов
|
||||
# 2. Сборку образов (с тегами v1.3.0, commit SHA, и latest)
|
||||
# 3. Деплой в k8s (если тег начинается с 'v')
|
||||
```
|
||||
|
||||
**Image tags created:**
|
||||
**Создаваемые теги образов:**
|
||||
- `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:latest`
|
||||
|
||||
---
|
||||
|
||||
### Pipeline 5: **Deploy-Only**
|
||||
**Trigger:** Tag with commit message containing `deploy_only:`
|
||||
**Purpose:** Fast deploy of already-built images
|
||||
**Duration:** ~1 minute
|
||||
### Пайплайн 5: **Deploy-Only (Только деплой)**
|
||||
**Триггер:** Тег с сообщением коммита, содержащим `deploy_only:`
|
||||
**Назначение:** Быстрый деплой уже собранных образов
|
||||
**Длительность:** ~1 минута
|
||||
|
||||
**What it does:**
|
||||
- Skips building
|
||||
- Deploys specified images to Kubernetes
|
||||
- Useful for rolling back or promoting existing images
|
||||
**Что делает:**
|
||||
- Пропускает сборку
|
||||
- Деплоит указанные образы в Kubernetes
|
||||
- Полезно для отката или продвижения существующих образов
|
||||
|
||||
**Example workflow:**
|
||||
**Пример рабочего процесса:**
|
||||
```bash
|
||||
# Deploy existing images
|
||||
# Деплой существующих образов
|
||||
git commit --allow-empty -m "deploy_only: Deploy v1.2.9"
|
||||
git tag 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`
|
||||
**Purpose:** Deploy services to Kubernetes
|
||||
**Usage:**
|
||||
**Назначение:** Деплой сервисов в Kubernetes
|
||||
**Использование:**
|
||||
```bash
|
||||
./deploy.sh <tag> <commit-sha>
|
||||
./deploy.sh v1.3.0 abc1234
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Updates deployment manifests with new image tags
|
||||
- Applies manifests to cluster
|
||||
- Waits for rollouts to complete with timeout
|
||||
- Runs health checks after deployment
|
||||
- Shows pod status
|
||||
**Возможности:**
|
||||
- Обновляет deployment-манифесты новыми тегами образов
|
||||
- Применяет манифесты в кластер
|
||||
- Ожидает завершения rollout с таймаутом
|
||||
- Запускает проверки здоровья после деплоя
|
||||
- Показывает статус подов
|
||||
|
||||
### `rollback.sh`
|
||||
**Purpose:** Rollback deployments to previous version
|
||||
**Usage:**
|
||||
**Назначение:** Откат деплоев к предыдущей версии
|
||||
**Использование:**
|
||||
```bash
|
||||
# Rollback single service
|
||||
# Откат одного сервиса
|
||||
./rollback.sh telegram-listener
|
||||
|
||||
# Rollback all services
|
||||
# Откат всех сервисов
|
||||
./rollback.sh all
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Shows revision history
|
||||
- Performs kubectl rollout undo
|
||||
- Waits for rollback to complete
|
||||
- Runs health checks after rollback
|
||||
**Возможности:**
|
||||
- Показывает историю ревизий
|
||||
- Выполняет kubectl rollout undo
|
||||
- Ожидает завершения отката
|
||||
- Запускает проверки здоровья после отката
|
||||
|
||||
### `health-check.sh`
|
||||
**Purpose:** Check health of all Nocr services
|
||||
**Usage:**
|
||||
**Назначение:** Проверка здоровья всех сервисов NOCR
|
||||
**Использование:**
|
||||
```bash
|
||||
./health-check.sh
|
||||
```
|
||||
|
||||
**Checks:**
|
||||
- Pod status (Running/Ready)
|
||||
- Health endpoints (/health)
|
||||
- Recent events for failed pods
|
||||
**Проверяет:**
|
||||
- Статус подов (Running/Ready)
|
||||
- Health-эндпоинты (/health)
|
||||
- Последние события для упавших подов
|
||||
|
||||
---
|
||||
|
||||
## 📦 Optimizations
|
||||
## 📦 Оптимизации
|
||||
|
||||
### Shared NuGet Cache
|
||||
All pipelines use a shared temp volume for NuGet packages:
|
||||
- First `dotnet restore` downloads packages
|
||||
- Subsequent builds reuse cached packages
|
||||
- **~60% faster** than individual restores per service
|
||||
### Общий NuGet-кэш
|
||||
Все пайплайны используют общий временный volume для NuGet-пакетов:
|
||||
- Первый `dotnet restore` скачивает пакеты
|
||||
- Последующие сборки переиспользуют кэшированные пакеты
|
||||
- **~60% быстрее**, чем индивидуальное восстановление для каждого сервиса
|
||||
|
||||
### Parallel Execution
|
||||
- Contract publishing: 3 services in parallel
|
||||
- Docker builds: 3 parallel streams
|
||||
- Independent operations never block each other
|
||||
### Параллельное выполнение
|
||||
- Публикация контрактов: 3 сервиса параллельно
|
||||
- Сборка Docker: 3 параллельных потока
|
||||
- Независимые операции никогда не блокируют друг друга
|
||||
|
||||
### Kaniko Caching
|
||||
All Kaniko builds use:
|
||||
- `--cache=true` - Layer caching enabled
|
||||
- `--cache-repo=hub.musk.fun/k8s/cache/*` - Shared cache repo
|
||||
- `--compressed-caching=true` - Faster cache transfer
|
||||
### Кэширование Kaniko
|
||||
Все сборки Kaniko используют:
|
||||
- `--cache=true` - Включено кэширование слоев
|
||||
- `--cache-repo=hub.musk.fun/k8s/cache/*` - Общий репозиторий кэша
|
||||
- `--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
|
||||
services:
|
||||
@ -211,91 +211,149 @@ services:
|
||||
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_password` - Docker registry password
|
||||
- `nuget_musk_api_key` - NuGet feed API key
|
||||
- `hub_username` - Имя пользователя Docker registry
|
||||
- `hub_password` - Пароль Docker registry
|
||||
- `nuget_musk_api_key` - API-ключ NuGet-фида
|
||||
|
||||
---
|
||||
|
||||
## 📊 Pipeline Decision Tree
|
||||
## 📊 Дерево решений пайплайна
|
||||
|
||||
```
|
||||
Push to feature/* → Feature Validation (build + test)
|
||||
Push to main → Main Validation (build + test)
|
||||
Push в feature/* → Feature Validation (сборка + тесты)
|
||||
Push в main → Main Validation (сборка + тесты)
|
||||
|
||||
Tag + "contracts_only:" → Contracts Publish
|
||||
Tag + "deploy_only:" → Deploy Only
|
||||
Tag (no markers) → Full Release (contracts → images → deploy)
|
||||
Тег + "contracts_only:" → Contracts Publish
|
||||
Тег + "deploy_only:" → Deploy Only
|
||||
Тег (без маркеров) → Full Release (контракты → образы → деплой)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Best Practices
|
||||
## 🎓 Лучшие практики
|
||||
|
||||
1. **Feature Branches**
|
||||
- Always create feature branches for new work
|
||||
- Let CI validate before merging to main
|
||||
1. **Функциональные ветки**
|
||||
- Всегда создавайте функциональные ветки для новой работы
|
||||
- Дайте CI валидировать перед мерджем в main
|
||||
|
||||
2. **Contracts Changes**
|
||||
- Use `contracts_only:` for quick contract updates
|
||||
- Other services can update references immediately
|
||||
2. **Изменения контрактов**
|
||||
- Используйте `contracts_only:` для быстрого обновления контрактов
|
||||
- Другие сервисы могут сразу обновить ссылки
|
||||
|
||||
3. **Release Process**
|
||||
- Tag only from main branch
|
||||
- Use semantic versioning (v1.2.3)
|
||||
- Tags starting with `v` auto-deploy to k8s
|
||||
3. **Процесс релиза**
|
||||
- Создавайте теги только из ветки main
|
||||
- Используйте семантическое версионирование (v1.2.3)
|
||||
- Теги, начинающиеся с `v`, автоматически деплоятся в k8s
|
||||
|
||||
4. **Emergency Rollback**
|
||||
4. **Экстренный откат**
|
||||
```bash
|
||||
# Quick rollback via deploy-only
|
||||
# Быстрый откат через deploy-only
|
||||
git commit --allow-empty -m "deploy_only: Rollback to v1.2.8"
|
||||
git tag 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
|
||||
cd /flea/_deploy/scripts
|
||||
./rollback.sh all
|
||||
```
|
||||
|
||||
5. **Monitoring Deployments**
|
||||
- Watch Drone UI for pipeline progress
|
||||
- Check pod logs: `kubectl logs -f deployment/telegram-listener -n nocr`
|
||||
- Run health checks: `./_deploy/scripts/health-check.sh`
|
||||
5. **Мониторинг деплоев**
|
||||
- Следите за UI Drone для прогресса пайплайна
|
||||
- Проверяйте логи подов: `kubectl logs -f deployment/telegram-listener -n nocr`
|
||||
- Запускайте проверки здоровья: `./_deploy/scripts/health-check.sh`
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
## 🐛 Устранение неполадок
|
||||
|
||||
### Pipeline stuck on "Waiting for contracts"
|
||||
**Cause:** Contract publish failed
|
||||
**Solution:** Check NuGet feed, verify API key
|
||||
### Пайплайн завис на "Waiting for contracts"
|
||||
**Причина:** Публикация контракта упала
|
||||
**Решение:** Проверьте NuGet-фид, проверьте API-ключ
|
||||
|
||||
### Docker build fails with "unauthorized"
|
||||
**Cause:** Invalid registry credentials
|
||||
**Solution:** Update `hub_username` and `hub_password` secrets
|
||||
### Сборка Docker падает с ошибкой "unauthorized"
|
||||
**Причина:** Неверные учетные данные registry
|
||||
**Решение:** Обновите секреты `hub_username` и `hub_password`
|
||||
|
||||
### Tests fail with "Cannot connect to Docker daemon"
|
||||
**Cause:** Testcontainers can't reach Docker-in-Docker service
|
||||
**Solution:** Check `DOCKER_HOST` environment variable is set correctly
|
||||
### Тесты падают с ошибкой "Cannot connect to Docker daemon"
|
||||
**Причина:** Testcontainers не может достичь Docker-in-Docker сервиса
|
||||
**Решение:** Проверьте, что переменная окружения `DOCKER_HOST` установлена правильно
|
||||
|
||||
### Deployment fails with "ImagePullBackOff"
|
||||
**Cause:** Image not found in registry
|
||||
**Solution:** Verify image was built and pushed successfully in previous step
|
||||
### Деплой падает с ошибкой "ImagePullBackOff"
|
||||
**Причина:** Образ не найден в registry
|
||||
**Решение:** Проверьте, что образ был собран и запушен успешно на предыдущем этапе
|
||||
|
||||
### 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/)
|
||||
- [Kaniko Documentation](https://github.com/GoogleContainerTools/kaniko)
|
||||
- [Testcontainers for .NET](https://dotnet.testcontainers.org/)
|
||||
- [Kubernetes Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
|
||||
- [Документация Drone CI](https://docs.drone.io/)
|
||||
- [Документация Kaniko](https://github.com/GoogleContainerTools/kaniko)
|
||||
- [Testcontainers для .NET](https://dotnet.testcontainers.org/)
|
||||
- [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-команде.
|
||||
|
||||
378
architecture.md
378
architecture.md
@ -1,47 +1,389 @@
|
||||
# Архитектура системы NOCR
|
||||
|
||||
Диаграмма взаимодействия между сервисами системы мониторинга Telegram-каналов.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
TelegramListener <|-- Bus
|
||||
TextMatcher <|-- TelegramClient
|
||||
TextMatcher <|-- Bus
|
||||
Bus <|-- TextMatcher
|
||||
TelegramClient <|-- Bus
|
||||
Users <|-- TelegramClient
|
||||
Bus <|-- TelegramListener
|
||||
TelegramListener --|> Bus : publishes
|
||||
Bus --|> TextMatcher : subscribes
|
||||
TextMatcher --|> Bus : publishes
|
||||
Bus --|> TelegramClient : subscribes
|
||||
TelegramClient --|> Users : REST API
|
||||
TelegramClient --|> TextMatcher : REST API
|
||||
|
||||
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 {
|
||||
+MessageReceived
|
||||
-TextMatcher.TextMatchCreated
|
||||
<<Сканер каналов>>
|
||||
+publishes: MessageReceived
|
||||
+publishes: MessageEdited
|
||||
---
|
||||
WTelegramClient (MTProto API)
|
||||
Хранение сессий пользователей
|
||||
}
|
||||
|
||||
class TextMatcher {
|
||||
+TextMatchCreated
|
||||
+TextMatchMatched
|
||||
-TelegramListener.MessageReceived
|
||||
+long Create(CreateTextMatchRequest request)
|
||||
<<Обработчик совпадений>>
|
||||
+publishes: TextSubscriptionMatched
|
||||
+publishes: TextSubscriptionUpdated
|
||||
-subscribes: MessageReceived
|
||||
-subscribes: MessageEdited
|
||||
---
|
||||
REST API:
|
||||
+long Create(CreateTextMatchRequest)
|
||||
+TextMatchData? GetById(long id)
|
||||
+TextMatchData[] GetByUserId(long userId)
|
||||
+void Delete(long id)
|
||||
+void Activate(long id)
|
||||
+void Disable(long id)
|
||||
---
|
||||
БД: История совпадений (MariaDB)
|
||||
Проверка регулярных выражений
|
||||
}
|
||||
|
||||
class Users {
|
||||
+long Create(CreateUserRequest request)
|
||||
<<Управление пользователями>>
|
||||
---
|
||||
REST API:
|
||||
+long Create(CreateUserRequest)
|
||||
+UserData? GetById(long id)
|
||||
+UserData? GetByIdentity(UserIdentityType identityType, string identity)
|
||||
+UserData? GetByIdentity(type, identity)
|
||||
---
|
||||
БД: Пользователи и настройки (MariaDB)
|
||||
}
|
||||
|
||||
class TelegramClient {
|
||||
-TextMatcher.TextMatchMatched
|
||||
<<Telegram Bot интерфейс>>
|
||||
-subscribes: TextSubscriptionMatched
|
||||
-subscribes: TextSubscriptionUpdated
|
||||
---
|
||||
Telegram.Bot (Bot API)
|
||||
Обработка команд пользователей
|
||||
Отправка уведомлений
|
||||
---
|
||||
REST клиенты:
|
||||
-Users.Create()
|
||||
-Users.GetById()
|
||||
-Users.GetByIdentity()
|
||||
-TextMatcher.GetByUserId()
|
||||
-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_
|
||||
|
||||
Loading…
Reference in New Issue
Block a user