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

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)
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
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:
[![Build Status](https://drone.musk.fun/api/badges/nocr/flea/status.svg?ref=refs/heads/main)](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)

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**
**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-команде.

View File

@ -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_