- Unify API: lib/api.ts uses /api/v1, inbox uses /api/inbox (rewrites) - Remove localhost refs: openapi, inbox page - Add rewrites: /api/inbox|tmc -> inbox-server, /api/v1 -> FastAPI - Add stub routes: knowledge/insights, recommendations, search, log-error - Transfer from PAPA: prompts (inspection, tmc), scripts, supabase, data/tmc-requests - Fix inbox-server: ORDER BY created_at, package.json - Remove redundant app/api/inbox/files route (rewrites handle it) - knowledge/ in gitignore (large PDFs) Co-authored-by: Cursor <cursoragent@cursor.com>
352 lines
9.5 KiB
Markdown
352 lines
9.5 KiB
Markdown
# Архитектура технологий системы
|
||
|
||
## Обзор
|
||
|
||
Система использует современный стек технологий для обеспечения масштабируемости, производительности и надёжности.
|
||
|
||
## Компоненты
|
||
|
||
### 1. PostgreSQL - CRUD и авторизация
|
||
|
||
**Назначение**: Основная база данных для операционных данных и авторизации
|
||
|
||
**Использование**:
|
||
- Хранение пользователей и ролей
|
||
- CRUD операции для воздушных судов, аудитов, рисков
|
||
- Транзакционные данные
|
||
- Связи между сущностями
|
||
|
||
**Конфигурация**:
|
||
```env
|
||
DB_HOST=localhost
|
||
DB_PORT=5432
|
||
DB_NAME=klg
|
||
DB_USER=klg
|
||
DB_PASSWORD=klg
|
||
```
|
||
|
||
**Файлы**:
|
||
- `lib/database/connection.ts` - подключение
|
||
- `lib/database/schema.sql` - схема БД
|
||
|
||
---
|
||
|
||
### 2. S3/MinIO + Parquet - Хранение данных
|
||
|
||
**Назначение**: Объектное хранилище для больших объёмов данных в формате Parquet
|
||
|
||
**Использование**:
|
||
- Хранение исторических данных
|
||
- Экспорт/импорт больших объёмов
|
||
- Архивные копии
|
||
- Данные для аналитики
|
||
|
||
**Конфигурация**:
|
||
```env
|
||
MINIO_ENDPOINT=http://localhost:9000
|
||
MINIO_ACCESS_KEY=minioadmin
|
||
MINIO_SECRET_KEY=minioadmin
|
||
MINIO_BUCKET=klg-data
|
||
```
|
||
|
||
**Файлы**:
|
||
- `lib/storage/s3-client.ts` - клиент S3/MinIO
|
||
- `lib/parquet/polars-utils.ts` - утилиты для Parquet
|
||
|
||
**Использование**:
|
||
```typescript
|
||
import { uploadParquetFile, getParquetFile } from '@/lib/storage/s3-client';
|
||
|
||
// Загрузка Parquet файла
|
||
await uploadParquetFile('aircraft/data.parquet', buffer);
|
||
|
||
// Получение файла
|
||
const data = await getParquetFile('aircraft/data.parquet');
|
||
```
|
||
|
||
---
|
||
|
||
### 3. ClickHouse - Аналитика и тяжёлые списки
|
||
|
||
**Назначение**: Колоночная БД для аналитических запросов и больших объёмов данных
|
||
|
||
**Использование**:
|
||
- Аналитические запросы
|
||
- Агрегации по большим объёмам данных
|
||
- Отчёты и дашборды
|
||
- Исторические данные
|
||
|
||
**Конфигурация**:
|
||
```env
|
||
CLICKHOUSE_URL=http://localhost:8123
|
||
CLICKHOUSE_DB=klg_analytics
|
||
CLICKHOUSE_USER=default
|
||
CLICKHOUSE_PASSWORD=
|
||
```
|
||
|
||
**Файлы**:
|
||
- `lib/analytics/clickhouse-client.ts` - клиент ClickHouse
|
||
- `scripts/clickhouse-init/init.sql` - инициализация схемы
|
||
|
||
**Использование**:
|
||
```typescript
|
||
import { queryClickHouse, insertClickHouse } from '@/lib/analytics/clickhouse-client';
|
||
|
||
// Аналитический запрос
|
||
const analytics = await queryClickHouse(`
|
||
SELECT operator, COUNT(*) as total
|
||
FROM aircraft_analytics
|
||
GROUP BY operator
|
||
`);
|
||
|
||
// Вставка данных
|
||
await insertClickHouse('aircraft_analytics', data);
|
||
```
|
||
|
||
---
|
||
|
||
### 4. OpenSearch - Полнотекстовый поиск
|
||
|
||
**Назначение**: Поиск по всем данным системы с поддержкой полнотекстового поиска
|
||
|
||
**Использование**:
|
||
- Поиск воздушных судов
|
||
- Поиск в документах
|
||
- Поиск в аудитах и рисках
|
||
- Нечёткий поиск (fuzzy search)
|
||
|
||
**Конфигурация**:
|
||
```env
|
||
OPENSEARCH_URL=http://localhost:9200
|
||
OPENSEARCH_USERNAME=
|
||
OPENSEARCH_PASSWORD=
|
||
```
|
||
|
||
**Файлы**:
|
||
- `lib/search/opensearch-client.ts` - клиент OpenSearch
|
||
|
||
**Использование**:
|
||
```typescript
|
||
import { searchAircraft, indexDocument } from '@/lib/search/opensearch-client';
|
||
|
||
// Индексация документа
|
||
await indexDocument('aircraft', aircraftId, aircraftData);
|
||
|
||
// Поиск
|
||
const results = await searchAircraft('RA-12345', {
|
||
operator: 'Аэрофлот',
|
||
status: 'Активен'
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
### 5. Airflow/Prefect + Python (Polars/DuckDB) - Пайплайны
|
||
|
||
**Назначение**: Оркестрация ETL пайплайнов для обработки данных
|
||
|
||
**Использование**:
|
||
- Импорт данных из ФАВТ
|
||
- Обработка больших объёмов данных
|
||
- Конвертация форматов (CSV → Parquet)
|
||
- Загрузка данных в аналитические хранилища
|
||
|
||
**Конфигурация**:
|
||
```env
|
||
PREFECT_API_URL=http://localhost:4200/api
|
||
MINIO_ENDPOINT=http://localhost:9000
|
||
CLICKHOUSE_URL=http://localhost:8123
|
||
```
|
||
|
||
**Файлы**:
|
||
- `scripts/pipelines/aircraft_pipeline.py` - пайплайн обработки ВС
|
||
- `scripts/pipelines/favt_import_pipeline.py` - пайплайн импорта ФАВТ
|
||
- `scripts/pipelines/requirements.txt` - Python зависимости
|
||
|
||
**Установка**:
|
||
```bash
|
||
pip install -r scripts/pipelines/requirements.txt
|
||
```
|
||
|
||
**Запуск пайплайна**:
|
||
```bash
|
||
# Через Prefect CLI
|
||
prefect deployment run aircraft-data-pipeline
|
||
|
||
# Или напрямую
|
||
python scripts/pipelines/aircraft_pipeline.py
|
||
```
|
||
|
||
---
|
||
|
||
### 6. OpenAPI → Генерация типов на фронт
|
||
|
||
**Назначение**: Автоматическая генерация TypeScript типов из OpenAPI схемы
|
||
|
||
**Использование**:
|
||
- Типобезопасность API
|
||
- Автодополнение в IDE
|
||
- Валидация запросов/ответов
|
||
- Документация API
|
||
|
||
**Файлы**:
|
||
- `openapi.json` - OpenAPI схема
|
||
- `scripts/openapi-generate.ts` - генератор типов
|
||
|
||
**Генерация типов**:
|
||
```bash
|
||
npm run generate:types
|
||
```
|
||
|
||
**Использование**:
|
||
```typescript
|
||
import { Aircraft, APIEndpoints } from '@/lib/api/generated-types';
|
||
|
||
// Типизированный запрос
|
||
const aircraft: Aircraft = await fetch('/api/aircraft/123').then(r => r.json());
|
||
```
|
||
|
||
---
|
||
|
||
## Docker Compose
|
||
|
||
Все сервисы запускаются через Docker Compose:
|
||
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
**Сервисы**:
|
||
- `db` - PostgreSQL (5432)
|
||
- `minio` - MinIO S3 (9000, 9001)
|
||
- `clickhouse` - ClickHouse (8123, 9000)
|
||
- `opensearch` - OpenSearch (9200)
|
||
- `opensearch-dashboards` - Dashboards (5601)
|
||
- `redis` - Redis (6379)
|
||
- `prefect` - Prefect UI (4200)
|
||
- `backend` - FastAPI (8000)
|
||
- `frontend` - Next.js (3000)
|
||
|
||
---
|
||
|
||
## Поток данных
|
||
|
||
### Импорт данных из ФАВТ
|
||
|
||
1. **Python скрипт** (`fetch_favt_registry.py`) загружает CSV с сайта ФАВТ
|
||
2. **Prefect пайплайн** (`favt_import_pipeline.py`):
|
||
- Читает CSV
|
||
- Конвертирует в Parquet через Polars
|
||
- Сохраняет в S3/MinIO
|
||
- Импортирует в PostgreSQL
|
||
3. **Данные синхронизируются**:
|
||
- PostgreSQL - для операционных запросов
|
||
- ClickHouse - для аналитики
|
||
- OpenSearch - для поиска
|
||
|
||
### Обработка данных
|
||
|
||
1. **Пайплайн** (`aircraft_pipeline.py`):
|
||
- Загружает данные из PostgreSQL
|
||
- Обрабатывает через Polars/DuckDB
|
||
- Сохраняет в Parquet
|
||
- Загружает в S3 и ClickHouse
|
||
|
||
### Поиск
|
||
|
||
1. При создании/обновлении записи:
|
||
- Данные сохраняются в PostgreSQL
|
||
- Индексируются в OpenSearch
|
||
2. При поиске:
|
||
- Запрос идёт в OpenSearch
|
||
- Результаты возвращаются с релевантностью
|
||
|
||
---
|
||
|
||
## Переменные окружения
|
||
|
||
Создайте файл `.env.local`:
|
||
|
||
```env
|
||
# PostgreSQL
|
||
DB_HOST=localhost
|
||
DB_PORT=5432
|
||
DB_NAME=klg
|
||
DB_USER=klg
|
||
DB_PASSWORD=klg
|
||
|
||
# MinIO/S3
|
||
MINIO_ENDPOINT=http://localhost:9000
|
||
MINIO_ACCESS_KEY=minioadmin
|
||
MINIO_SECRET_KEY=minioadmin
|
||
MINIO_BUCKET=klg-data
|
||
|
||
# ClickHouse
|
||
CLICKHOUSE_URL=http://localhost:8123
|
||
CLICKHOUSE_DB=klg_analytics
|
||
CLICKHOUSE_USER=default
|
||
CLICKHOUSE_PASSWORD=
|
||
|
||
# OpenSearch
|
||
OPENSEARCH_URL=http://localhost:9200
|
||
|
||
# Prefect
|
||
PREFECT_API_URL=http://localhost:4200/api
|
||
|
||
# Redis
|
||
REDIS_HOST=localhost
|
||
REDIS_PORT=6379
|
||
```
|
||
|
||
---
|
||
|
||
## Запуск системы
|
||
|
||
1. **Запуск всех сервисов**:
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
2. **Инициализация ClickHouse**:
|
||
```bash
|
||
docker-compose exec clickhouse clickhouse-client < scripts/clickhouse-init/init.sql
|
||
```
|
||
|
||
3. **Создание bucket в MinIO**:
|
||
- Откройте http://localhost:9001
|
||
- Логин: minioadmin / minioadmin
|
||
- Создайте bucket `klg-data`
|
||
|
||
4. **Генерация типов из OpenAPI**:
|
||
```bash
|
||
npm run generate:types
|
||
```
|
||
|
||
5. **Запуск пайплайнов**:
|
||
```bash
|
||
# Установка зависимостей
|
||
pip install -r scripts/pipelines/requirements.txt
|
||
|
||
# Запуск Prefect сервера (уже в Docker)
|
||
# Запуск пайплайна
|
||
prefect deployment run aircraft-data-pipeline
|
||
```
|
||
|
||
---
|
||
|
||
## Мониторинг
|
||
|
||
- **Prefect UI**: http://localhost:4200
|
||
- **MinIO Console**: http://localhost:9001
|
||
- **OpenSearch Dashboards**: http://localhost:5601
|
||
- **ClickHouse**: http://localhost:8123/play
|
||
|
||
---
|
||
|
||
## Дополнительная информация
|
||
|
||
См. также:
|
||
- `docs/MASHTABIRUEMOST.md` - масштабируемость
|
||
- `docs/DEPLOYMENT.md` - развёртывание
|
||
- `scripts/pipelines/` - примеры пайплайнов
|