stuff
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Mobile App CI / test (push) Waiting to run
Mobile App CI / build-android (push) Blocked by required conditions
Mobile App CI / build-ios (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Mobile App CI / test (push) Waiting to run
Mobile App CI / build-android (push) Blocked by required conditions
Mobile App CI / build-ios (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
This commit is contained in:
parent
9c2456f685
commit
8d3d4cd1f7
5 changed files with 2105 additions and 0 deletions
|
|
@ -0,0 +1,57 @@
|
||||||
|
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('MatrixTestQuestionBody', () {
|
||||||
|
test('json roundtrip preserves fields', () {
|
||||||
|
final body = MatrixTestQuestionBody(
|
||||||
|
id: 'q1',
|
||||||
|
matrixSize: 3,
|
||||||
|
word: 'hola',
|
||||||
|
answer: 'card_1',
|
||||||
|
cards: const [
|
||||||
|
MatrixCardDto(
|
||||||
|
id: 'card_1',
|
||||||
|
image: '/api/v2/packs/p1/cards/card_1/image',
|
||||||
|
original: 'hola',
|
||||||
|
translation: 'привет',
|
||||||
|
),
|
||||||
|
MatrixCardDto(
|
||||||
|
id: 'card_2',
|
||||||
|
image: '/api/v2/packs/p1/cards/card_2/image',
|
||||||
|
original: 'adios',
|
||||||
|
translation: 'пока',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final json = body.toJson();
|
||||||
|
final parsed = AbstractTestQuestion.fromJson(json) as MatrixTestQuestionBody;
|
||||||
|
|
||||||
|
expect(parsed.questionType, TestQuestionType.matrix);
|
||||||
|
expect(parsed.id, 'q1');
|
||||||
|
expect(parsed.matrixSize, 3);
|
||||||
|
expect(parsed.word, 'hola');
|
||||||
|
expect(parsed.answer, 'card_1');
|
||||||
|
expect(parsed.cards.length, 2);
|
||||||
|
expect(parsed.cards.first.original, 'hola');
|
||||||
|
expect(parsed.cards.first.translation, 'привет');
|
||||||
|
expect(parsed.cards.first.image, contains('/cards/card_1/image'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('matrixSize falls back to default when missing', () {
|
||||||
|
final json = <String, dynamic>{
|
||||||
|
'questionType': 'matrix',
|
||||||
|
'id': 'q1',
|
||||||
|
'word': 'hola',
|
||||||
|
'answer': 'card_1',
|
||||||
|
'buttons': const [],
|
||||||
|
};
|
||||||
|
|
||||||
|
final parsed = AbstractTestQuestion.fromJson(json) as MatrixTestQuestionBody;
|
||||||
|
expect(parsed.matrixSize, 3);
|
||||||
|
expect(parsed.cards, isEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
121
mnemo_cards_common/test/user_dto_telegram_test.dart
Normal file
121
mnemo_cards_common/test/user_dto_telegram_test.dart
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('UserDto telegram field', () {
|
||||||
|
test('should serialize and deserialize with telegram', () {
|
||||||
|
final userDto = UserDto(
|
||||||
|
id: 'test-id',
|
||||||
|
name: 'Test User',
|
||||||
|
email: 'test@example.com',
|
||||||
|
telegram: '@testuser',
|
||||||
|
admin: false,
|
||||||
|
packs: ['pack1', 'pack2'],
|
||||||
|
purchases: ['purchase1'],
|
||||||
|
);
|
||||||
|
|
||||||
|
final json = userDto.toJson();
|
||||||
|
expect(json['telegram'], equals('@testuser'));
|
||||||
|
expect(json['email'], equals('test@example.com'));
|
||||||
|
|
||||||
|
final deserialized = UserDto.fromJson(json);
|
||||||
|
expect(deserialized.telegram, equals('@testuser'));
|
||||||
|
expect(deserialized.email, equals('test@example.com'));
|
||||||
|
expect(deserialized.name, equals('Test User'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle null telegram', () {
|
||||||
|
final userDto = UserDto(
|
||||||
|
id: 'test-id',
|
||||||
|
name: 'Test User',
|
||||||
|
email: 'test@example.com',
|
||||||
|
telegram: null,
|
||||||
|
admin: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final json = userDto.toJson();
|
||||||
|
expect(json['telegram'], isNull);
|
||||||
|
|
||||||
|
final deserialized = UserDto.fromJson(json);
|
||||||
|
expect(deserialized.telegram, isNull);
|
||||||
|
expect(deserialized.email, equals('test@example.com'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle missing telegram in JSON', () {
|
||||||
|
final json = {
|
||||||
|
'id': 'test-id',
|
||||||
|
'name': 'Test User',
|
||||||
|
'email': 'test@example.com',
|
||||||
|
'admin': false,
|
||||||
|
'packs': <String>[],
|
||||||
|
'purchases': <String>[],
|
||||||
|
};
|
||||||
|
|
||||||
|
final userDto = UserDto.fromJson(json);
|
||||||
|
expect(userDto.telegram, isNull);
|
||||||
|
expect(userDto.email, equals('test@example.com'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should support telegram without email for Telegram-only users', () {
|
||||||
|
final userDto = UserDto(
|
||||||
|
id: 'test-id',
|
||||||
|
name: 'Telegram User',
|
||||||
|
email: null,
|
||||||
|
telegram: '@telegram_only',
|
||||||
|
admin: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final json = userDto.toJson();
|
||||||
|
expect(json['telegram'], equals('@telegram_only'));
|
||||||
|
expect(json['email'], isNull);
|
||||||
|
|
||||||
|
final deserialized = UserDto.fromJson(json);
|
||||||
|
expect(deserialized.telegram, equals('@telegram_only'));
|
||||||
|
expect(deserialized.email, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with copyWith for telegram', () {
|
||||||
|
final userDto = UserDto(
|
||||||
|
id: 'test-id',
|
||||||
|
name: 'Test User',
|
||||||
|
email: 'test@example.com',
|
||||||
|
telegram: '@oldusername',
|
||||||
|
admin: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final updated = userDto.copyWith(telegram: '@newusername');
|
||||||
|
expect(updated.telegram, equals('@newusername'));
|
||||||
|
expect(updated.email, equals('test@example.com'));
|
||||||
|
expect(userDto.telegram, equals('@oldusername')); // Original unchanged
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle both email and telegram contact methods', () {
|
||||||
|
final userDto = UserDto(
|
||||||
|
id: 'test-id',
|
||||||
|
name: 'Test User',
|
||||||
|
email: 'user@example.com',
|
||||||
|
telegram: '@testuser',
|
||||||
|
admin: true,
|
||||||
|
packs: ['pack1'],
|
||||||
|
purchases: ['purchase1'],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(userDto.email, equals('user@example.com'));
|
||||||
|
expect(userDto.telegram, equals('@testuser'));
|
||||||
|
expect(userDto.admin, isTrue);
|
||||||
|
|
||||||
|
final json = userDto.toJson();
|
||||||
|
final deserialized = UserDto.fromJson(json);
|
||||||
|
|
||||||
|
expect(deserialized.email, equals('user@example.com'));
|
||||||
|
expect(deserialized.telegram, equals('@testuser'));
|
||||||
|
expect(deserialized.admin, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('empty UserDto should have null telegram', () {
|
||||||
|
final empty = UserDto.empty;
|
||||||
|
expect(empty.telegram, isNull);
|
||||||
|
expect(empty.email, isNull);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
32
plans/README.md
Normal file
32
plans/README.md
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# 📋 Планы на будущее
|
||||||
|
|
||||||
|
Эта папка содержит планы развития проекта Mnemo Cards.
|
||||||
|
|
||||||
|
## Структура
|
||||||
|
|
||||||
|
Планы сохраняются в формате Markdown с описанием задач, архитектурных решений и стратегий развития.
|
||||||
|
|
||||||
|
## Текущие планы
|
||||||
|
|
||||||
|
- **[микросервисная_архитектура.md](./микросервисная_архитектура.md)** - План разделения монолитного backend на микросервисы
|
||||||
|
|
||||||
|
## Формат планов
|
||||||
|
|
||||||
|
Каждый план содержит:
|
||||||
|
|
||||||
|
- **Название и краткое описание** - что планируется сделать
|
||||||
|
- **Анализ текущего состояния** - что есть сейчас
|
||||||
|
- **Детальный план** - как будет реализовано
|
||||||
|
- **TODO список** - конкретные задачи для выполнения
|
||||||
|
- **Риски и митигация** - потенциальные проблемы и способы их решения
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
Планы используются для:
|
||||||
|
|
||||||
|
- Архитектурных решений
|
||||||
|
- Долгосрочного планирования
|
||||||
|
- Документирования стратегических изменений
|
||||||
|
- Координации работы команды
|
||||||
|
|
||||||
|
После начала реализации плана, TODO список обновляется для отслеживания прогресса.
|
||||||
1352
plans/telegram_bot_product_features.md
Normal file
1352
plans/telegram_bot_product_features.md
Normal file
File diff suppressed because it is too large
Load diff
543
plans/микросервисная_архитектура.md
Normal file
543
plans/микросервисная_архитектура.md
Normal file
|
|
@ -0,0 +1,543 @@
|
||||||
|
---
|
||||||
|
name: Микросервисная архитектура Mnemo Cards
|
||||||
|
overview: План разделения монолитного backend на микросервисы с учетом независимого деплоя, разных технологий и организации команды. Используется гибридный подход к базам данных.
|
||||||
|
todos:
|
||||||
|
- id: analyze_dependencies
|
||||||
|
content: Проанализировать зависимости между модулями и создать карту зависимостей
|
||||||
|
status: pending
|
||||||
|
- id: design_api_gateway
|
||||||
|
content: Спроектировать API Gateway для маршрутизации запросов к микросервисам
|
||||||
|
status: pending
|
||||||
|
- id: create_shared_jwt_lib
|
||||||
|
content: Создать shared библиотеку для валидации JWT токенов
|
||||||
|
status: pending
|
||||||
|
- id: plan_database_migration
|
||||||
|
content: Спланировать миграцию базы данных (схемы/отдельные БД)
|
||||||
|
status: pending
|
||||||
|
- id: extract_auth_service
|
||||||
|
content: Выделить Auth Service как первый микросервис
|
||||||
|
status: pending
|
||||||
|
- id: extract_payment_service
|
||||||
|
content: Выделить Payment Service как второй микросервис
|
||||||
|
status: pending
|
||||||
|
- id: setup_service_communication
|
||||||
|
content: Настроить коммуникацию между сервисами (синхронная/асинхронная)
|
||||||
|
status: pending
|
||||||
|
- id: setup_monitoring
|
||||||
|
content: Настроить мониторинг и логирование для микросервисов
|
||||||
|
status: pending
|
||||||
|
- id: create_docker_compose
|
||||||
|
content: Создать docker-compose для локальной разработки всех микросервисов
|
||||||
|
status: pending
|
||||||
|
---
|
||||||
|
|
||||||
|
# План разделения на микросервисы
|
||||||
|
|
||||||
|
## Анализ текущей архитектуры
|
||||||
|
|
||||||
|
Текущий монолит включает следующие доменные области:
|
||||||
|
|
||||||
|
1. **Authentication & User Management** - JWT, Telegram auth, пользователи
|
||||||
|
2. **Content Management** - Packs, Cards, Tests, Games
|
||||||
|
3. **Payments & Subscriptions** - YooKassa, Google Play, RuStore
|
||||||
|
4. **Statistics & Analytics** - User statistics, achievements, word statistics
|
||||||
|
5. **Admin Panel** - Админские функции
|
||||||
|
6. **Telegram Bot** - Бот для авторизации
|
||||||
|
7. **Cron Jobs & Background Tasks** - Фоновые задачи
|
||||||
|
|
||||||
|
## Предлагаемое разделение на микросервисы
|
||||||
|
|
||||||
|
### 1. **Auth Service** (Сервис аутентификации)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- JWT токены (access/refresh)
|
||||||
|
- Регистрация/логин пользователей
|
||||||
|
- Telegram авторизация (генерация кодов)
|
||||||
|
- Управление пользователями (CRUD)
|
||||||
|
- ACL и авторизация
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `users`, `auth`, `tokens`, `refresh_tokens`, `telegram_auth_codes`
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/auth/*` (register, login, refresh, logout, telegram)
|
||||||
|
- `/api/v2/users/*` (CRUD пользователей)
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- PostgreSQL (собственная схема)
|
||||||
|
- Telegram Bot API (для авторизации)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf (можно оставить или перейти на Go/Node.js)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Критический сервис - должен быть высокодоступным
|
||||||
|
- Низкая задержка критична для всех запросов
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. **Content Service** (Сервис контента)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Управление паками карточек (CardPacks)
|
||||||
|
- Управление карточками (GameCards)
|
||||||
|
- Управление тестами (Tests)
|
||||||
|
- Управление играми (Games assets)
|
||||||
|
- Голоса карточек (CardVoices)
|
||||||
|
- Доступ к контенту (проверка прав доступа через Auth Service)
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `card_packs`, `game_cards`, `card_pack_cards`, `card_voices`, `tests`, `tasks`
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/packs/*`
|
||||||
|
- `/api/v2/tests/*`
|
||||||
|
- `/api/v2/games/*`
|
||||||
|
- `/api/v2/voice/*`
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- PostgreSQL (собственная схема или shared с Payments для связей)
|
||||||
|
- Auth Service (проверка доступа через API или shared token validation)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf (можно перейти на Python/FastAPI для удобства работы с контентом)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Статические файлы (изображения, аудио) - можно вынести в CDN/Storage
|
||||||
|
- Высокая нагрузка на чтение
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. **Payment Service** (Сервис платежей)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Обработка платежей через YooKassa
|
||||||
|
- Обработка IAP (Google Play, RuStore)
|
||||||
|
- Управление промокодами
|
||||||
|
- Управление скидками (discounts)
|
||||||
|
- Покупка паков
|
||||||
|
- Webhooks от платежных систем
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `payments`, `promo_codes`, `discounts`, `subscriptions` (или отдельный сервис)
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/purchases/*`
|
||||||
|
- `/api/v2/promocodes/*`
|
||||||
|
- `/api/v2/discounts/*`
|
||||||
|
- `/api/webhooks/yookassa`, `/api/webhooks/google-play`, `/api/webhooks/rustore`
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- PostgreSQL (собственная схема)
|
||||||
|
- Auth Service (проверка пользователя)
|
||||||
|
- Content Service (информация о паках для покупки)
|
||||||
|
- YooKassa API, Google Play API, RuStore API
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf или Node.js/TypeScript (удобная работа с webhooks)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Высокие требования к безопасности
|
||||||
|
- Идемпотентность операций
|
||||||
|
- Обработка webhooks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. **Subscription Service** (Сервис подписок)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Управление подписками пользователей
|
||||||
|
- Проверка активности подписки
|
||||||
|
- Фичи подписки
|
||||||
|
- Автопродление (через cron)
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `subscriptions` (может быть shared с Payment Service на этапе миграции)
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/subscriptions/*`
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- PostgreSQL (собственная схема или shared с Payment)
|
||||||
|
- Auth Service (проверка пользователя)
|
||||||
|
- Payment Service (создание подписки через платеж)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf или отдельный микросервис
|
||||||
|
|
||||||
|
**Вариант:** Можно объединить с Payment Service на первом этапе, если логика тесно связана.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. **Statistics Service** (Сервис статистики)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Статистика пользователей (user statistics)
|
||||||
|
- Статистика по словам (word statistics)
|
||||||
|
- Достижения (achievements)
|
||||||
|
- Сессии обучения (study sessions)
|
||||||
|
- Аналитика и отчеты
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `user_datas`, `word_statistics`, `achievements`, `study_sessions`, `pack_progress`
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/users/me/statistics/*`
|
||||||
|
- `/api/v2/users/me/achievements`
|
||||||
|
- `/api/v2/users/me/sessions`
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- PostgreSQL (собственная схема или отдельная БД для аналитики - TimescaleDB/ClickHouse)
|
||||||
|
- Auth Service (проверка пользователя)
|
||||||
|
- Content Service (информация о паках/карточках)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf или Python (удобно для аналитики) или Go (высокая производительность)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Высокая нагрузка на запись (tracking событий)
|
||||||
|
- Возможность использовать TimescaleDB для временных рядов
|
||||||
|
- Отложенная обработка данных (бэтчинг)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. **Admin Service** (Админ панель)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Админская авторизация
|
||||||
|
- Управление контентом (CRUD паков, карточек)
|
||||||
|
- Аналитика для админов
|
||||||
|
- Управление пользователями
|
||||||
|
- Audit логирование
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- `audit` (отдельная таблица для логирования действий)
|
||||||
|
- Использует данные из других сервисов
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/admin/*`
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- Auth Service (проверка админ прав)
|
||||||
|
- Content Service (управление контентом)
|
||||||
|
- Payment Service (управление платежами)
|
||||||
|
- Statistics Service (аналитика)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf (можно оставить текущий стек)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Агрегирует данные из нескольких сервисов
|
||||||
|
- Требует высоких прав доступа
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. **Telegram Bot Service** (Сервис Telegram бота)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Обработка команд Telegram бота
|
||||||
|
- Генерация кодов авторизации для веба
|
||||||
|
- Интеграция с Auth Service
|
||||||
|
|
||||||
|
**База данных:**
|
||||||
|
|
||||||
|
- Может использовать shared `telegram_auth_codes` или собственную
|
||||||
|
|
||||||
|
**API Endpoints:**
|
||||||
|
|
||||||
|
- `/api/v2/telegram-bot/*`
|
||||||
|
- Telegram Bot API webhook
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- Auth Service (создание/проверка кодов)
|
||||||
|
- Telegram Bot API
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart + Shelf или Node.js/TypeScript (удобные библиотеки для Telegram)
|
||||||
|
|
||||||
|
**Особенности:**
|
||||||
|
|
||||||
|
- Относительно изолированный сервис
|
||||||
|
- Может работать независимо
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. **Background Jobs Service** (Сервис фоновых задач)
|
||||||
|
|
||||||
|
**Ответственность:**
|
||||||
|
|
||||||
|
- Cron задачи (backup, проверка платежей, генерация промокодов, etc.)
|
||||||
|
- Асинхронная обработка задач
|
||||||
|
- Очереди задач (опционально)
|
||||||
|
|
||||||
|
**Зависимости:**
|
||||||
|
|
||||||
|
- Все остальные сервисы (для выполнения задач)
|
||||||
|
|
||||||
|
**Технологии:**
|
||||||
|
|
||||||
|
- Dart (текущий стек) или перейти на специализированное решение (Bull/BullMQ на Node.js, Celery на Python)
|
||||||
|
|
||||||
|
**Альтернатива:** Можно интегрировать в каждый сервис отдельно или использовать общий Job Queue (Redis + Worker).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Стратегия миграции
|
||||||
|
|
||||||
|
### Фаза 1: Подготовка (1-2 недели)
|
||||||
|
|
||||||
|
1. **Выделить общие компоненты:**
|
||||||
|
|
||||||
|
- Общие DTO/models в `mnemo_cards_common`
|
||||||
|
- Shared database connection pool
|
||||||
|
- API Gateway (опционально, можно использовать nginx/kong)
|
||||||
|
|
||||||
|
2. **Создать API Gateway:**
|
||||||
|
|
||||||
|
- Единая точка входа для клиентов
|
||||||
|
- Маршрутизация к микросервисам
|
||||||
|
- Агрегация запросов (если нужно)
|
||||||
|
- Rate limiting, CORS
|
||||||
|
|
||||||
|
### Фаза 2: Выделение критических сервисов (2-4 недели)
|
||||||
|
|
||||||
|
**Приоритет 1: Auth Service**
|
||||||
|
|
||||||
|
- Выделить аутентификацию в отдельный сервис
|
||||||
|
- Создать JWT validation library для других сервисов
|
||||||
|
- Мигрировать пользователей
|
||||||
|
|
||||||
|
**Приоритет 2: Payment Service**
|
||||||
|
|
||||||
|
- Выделить платежи
|
||||||
|
- Изолировать webhooks
|
||||||
|
- Мигрировать платежные данные
|
||||||
|
|
||||||
|
### Фаза 3: Выделение остальных сервисов (4-8 недель)
|
||||||
|
|
||||||
|
**Приоритет 3: Content Service**
|
||||||
|
|
||||||
|
- Выделить управление контентом
|
||||||
|
- Вынести статические файлы в CDN/Storage
|
||||||
|
|
||||||
|
**Приоритет 4: Statistics Service**
|
||||||
|
|
||||||
|
- Выделить статистику
|
||||||
|
- Оптимизировать запись данных (бэтчинг)
|
||||||
|
|
||||||
|
**Приоритет 5: Остальные сервисы**
|
||||||
|
|
||||||
|
- Admin Service
|
||||||
|
- Telegram Bot Service
|
||||||
|
- Background Jobs Service
|
||||||
|
|
||||||
|
### Фаза 4: Оптимизация (ongoing)
|
||||||
|
|
||||||
|
- Разделение баз данных (Database per Service)
|
||||||
|
- Кэширование (Redis)
|
||||||
|
- Message Queue для асинхронной коммуникации
|
||||||
|
- Мониторинг и логирование (ELK, Prometheus)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Схема коммуникации между сервисами
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TB
|
||||||
|
Client[Web Client] --> Gateway[API Gateway]
|
||||||
|
|
||||||
|
Gateway --> AuthService[Auth Service]
|
||||||
|
Gateway --> ContentService[Content Service]
|
||||||
|
Gateway --> PaymentService[Payment Service]
|
||||||
|
Gateway --> SubscriptionService[Subscription Service]
|
||||||
|
Gateway --> StatisticsService[Statistics Service]
|
||||||
|
Gateway --> AdminService[Admin Service]
|
||||||
|
|
||||||
|
TelegramBot[Telegram Bot] --> AuthService
|
||||||
|
TelegramBot --> Gateway
|
||||||
|
|
||||||
|
PaymentService --> AuthService
|
||||||
|
PaymentService --> ContentService
|
||||||
|
SubscriptionService --> AuthService
|
||||||
|
SubscriptionService --> PaymentService
|
||||||
|
StatisticsService --> AuthService
|
||||||
|
StatisticsService --> ContentService
|
||||||
|
AdminService --> AuthService
|
||||||
|
AdminService --> ContentService
|
||||||
|
AdminService --> PaymentService
|
||||||
|
AdminService --> StatisticsService
|
||||||
|
|
||||||
|
BackgroundJobs[Background Jobs] --> AuthService
|
||||||
|
BackgroundJobs --> PaymentService
|
||||||
|
BackgroundJobs --> StatisticsService
|
||||||
|
|
||||||
|
AuthService --> AuthDB[(Auth DB)]
|
||||||
|
ContentService --> ContentDB[(Content DB)]
|
||||||
|
PaymentService --> PaymentDB[(Payment DB)]
|
||||||
|
SubscriptionService --> SubscriptionDB[(Subscription DB)]
|
||||||
|
StatisticsService --> StatisticsDB[(Statistics DB)]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Рекомендации по базам данных (гибридный подход)
|
||||||
|
|
||||||
|
### Вариант 1: Shared Database на первом этапе
|
||||||
|
|
||||||
|
- Все сервисы используют одну БД, но разные схемы (namespaces)
|
||||||
|
- Упрощает миграцию
|
||||||
|
- Позволяет постепенно разделять
|
||||||
|
|
||||||
|
### Вариант 2: Database per Service (целевое состояние)
|
||||||
|
|
||||||
|
**Auth Service:**
|
||||||
|
|
||||||
|
- `auth_db` - users, tokens, refresh_tokens, telegram_auth_codes
|
||||||
|
|
||||||
|
**Content Service:**
|
||||||
|
|
||||||
|
- `content_db` - card_packs, game_cards, card_voices, tests, tasks
|
||||||
|
|
||||||
|
**Payment Service:**
|
||||||
|
|
||||||
|
- `payment_db` - payments, promo_codes, discounts
|
||||||
|
|
||||||
|
**Subscription Service:**
|
||||||
|
|
||||||
|
- `subscription_db` - subscriptions
|
||||||
|
|
||||||
|
**Statistics Service:**
|
||||||
|
|
||||||
|
- `statistics_db` - user_datas, word_statistics, achievements, study_sessions
|
||||||
|
- Или TimescaleDB для временных рядов
|
||||||
|
|
||||||
|
### Переходные связи:
|
||||||
|
|
||||||
|
Для связей между сервисами использовать:
|
||||||
|
|
||||||
|
- **API calls** - синхронная коммуникация (для проверки доступа, получения данных)
|
||||||
|
- **Event-driven** - асинхронная коммуникация (опционально, через message queue)
|
||||||
|
- **Shared IDs** - использование UUID для связи между сервисами
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Технологические рекомендации
|
||||||
|
|
||||||
|
### API Gateway
|
||||||
|
|
||||||
|
- **Kong** или **nginx** - для маршрутизации
|
||||||
|
- Или **Istio** для более сложных сценариев
|
||||||
|
|
||||||
|
### Service Mesh (опционально)
|
||||||
|
|
||||||
|
- **Istio** или **Linkerd** - для управления трафиком, безопасности, observability
|
||||||
|
|
||||||
|
### Message Queue (для асинхронной коммуникации)
|
||||||
|
|
||||||
|
- **Redis Pub/Sub** или **RabbitMQ** или **NATS**
|
||||||
|
- Для событий: payment_completed, user_registered, etc.
|
||||||
|
|
||||||
|
### Мониторинг
|
||||||
|
|
||||||
|
- **Prometheus + Grafana** - метрики
|
||||||
|
- **ELK Stack** (Elasticsearch, Logstash, Kibana) - логи
|
||||||
|
- **Jaeger** или **Zipkin** - distributed tracing
|
||||||
|
|
||||||
|
### Кэширование
|
||||||
|
|
||||||
|
- **Redis** - для кэширования токенов, контента, статистики
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Файлы, которые нужно будет изменить/создать
|
||||||
|
|
||||||
|
### Новые директории для микросервисов:
|
||||||
|
|
||||||
|
- `services/auth-service/`
|
||||||
|
- `services/content-service/`
|
||||||
|
- `services/payment-service/`
|
||||||
|
- `services/subscription-service/`
|
||||||
|
- `services/statistics-service/`
|
||||||
|
- `services/admin-service/`
|
||||||
|
- `services/telegram-bot-service/`
|
||||||
|
- `services/background-jobs-service/`
|
||||||
|
|
||||||
|
### Общие компоненты:
|
||||||
|
|
||||||
|
- `shared/jwt-validator/` - библиотека для валидации JWT
|
||||||
|
- `shared/database-migrations/` - миграции БД
|
||||||
|
- `shared/common-models/` - общие модели (уже есть в `mnemo_cards_common`)
|
||||||
|
|
||||||
|
### Конфигурация:
|
||||||
|
|
||||||
|
- `docker-compose.microservices.yml` - оркестрация всех сервисов
|
||||||
|
- `infrastructure/` - terraform/k8s конфигурации
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Критерии успешности разделения
|
||||||
|
|
||||||
|
1. ✅ Каждый сервис можно деплоить независимо
|
||||||
|
2. ✅ Сервисы могут использовать разные технологии
|
||||||
|
3. ✅ Отказ одного сервиса не ломает остальные
|
||||||
|
4. ✅ Легко масштабировать отдельные сервисы
|
||||||
|
5. ✅ Четкое разделение ответственности
|
||||||
|
6. ✅ Тестируемость каждого сервиса отдельно
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Риски и митигация
|
||||||
|
|
||||||
|
### Риск 1: Сложность отладки распределенной системы
|
||||||
|
|
||||||
|
**Митигация:** Использовать distributed tracing (Jaeger), централизованное логирование
|
||||||
|
|
||||||
|
### Риск 2: Сетевая задержка между сервисами
|
||||||
|
|
||||||
|
**Митигация:** Кэширование, асинхронная коммуникация где возможно, оптимизация API calls
|
||||||
|
|
||||||
|
### Риск 3: Консистентность данных между сервисами
|
||||||
|
|
||||||
|
**Митигация:** Event-driven архитектура, eventual consistency, saga pattern для транзакций
|
||||||
|
|
||||||
|
### Риск 4: Усложнение деплоя
|
||||||
|
|
||||||
|
**Митигация:** Docker Compose для разработки, Kubernetes для продакшена, CI/CD для каждого сервиса
|
||||||
Loading…
Reference in a new issue