diff --git a/CONFIGURATION.md b/CONFIGURATION.md index b3d2394..98a7e0b 100644 --- a/CONFIGURATION.md +++ b/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) diff --git a/README.md b/README.md index d13b852..b179fa0 100644 --- a/README.md +++ b/README.md @@ -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:` +**Длительность:** ~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) diff --git a/_deploy/README.md b/_deploy/README.md index ab08e5c..fb0702f 100644 --- a/_deploy/README.md +++ b/_deploy/README.md @@ -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:` -**Purpose:** Fast publish of contract packages without building images -**Duration:** ~2 minutes +### Пайплайн 3: **Contracts-Only Publish (Публикация только контрактов)** +**Триггер:** Тег с сообщением коммита, содержащим `contracts_only:` +**Назначение:** Быстрая публикация 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 ./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 -n nocr` + +Для вопросов по инфраструктуре обращайтесь к DevOps-команде. diff --git a/architecture.md b/architecture.md index 9dc548c..469d0f1 100644 --- a/architecture.md +++ b/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 + <> + +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 + <> + -subscribes: TextSubscriptionMatched + -subscribes: TextSubscriptionUpdated + --- + Telegram.Bot (Bot API) + Обработка команд пользователей + Отправка уведомлений + --- + REST клиенты: -Users.Create() -Users.GetById() -Users.GetByIdentity() -TextMatcher.GetByUserId() -TextMatcher.Create() } +``` -``` \ No newline at end of file +## Описание компонентов + +### 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_