mnemo_cards/mnemo_cards_backend/lib/main.dart

146 lines
4.6 KiB
Dart
Raw Normal View History

2025-11-16 11:25:27 +00:00
import 'dart:developer';
import 'dart:io';
import 'package:mnemo_cards_backend/api/mnemo_shelf.dart';
import 'package:mnemo_cards_backend/cron/add_free_packs.dart';
import 'package:mnemo_cards_backend/cron/backup.dart';
import 'package:mnemo_cards_backend/cron/cron_executor.dart';
import 'package:mnemo_cards_backend/cron/generate_promocodes.dart';
2025-12-13 13:27:05 +00:00
import 'package:mnemo_cards_backend/database/database.dart';
2025-11-16 11:25:27 +00:00
import 'package:mnemo_cards_backend/discounts/discounts_manager.dart';
import 'package:mnemo_cards_backend/user/user_manager.dart';
import 'package:mnemo_cards_backend/tests/test_manager.dart';
import 'api/di/injector.dart';
import 'cron/check_admins.dart';
import 'cron/check_payment.dart';
import 'cron/delete_old_archives.dart';
import 'cron/discount_campaign_task.dart';
import 'cron/tasks_seeder.dart';
import 'cron/test_generator.dart';
import 'cron/update_online_users.dart';
import 'packs/free_packs_distributor.dart';
2025-12-13 13:27:05 +00:00
late AppDatabase database;
2025-11-16 11:25:27 +00:00
late final String WORK_DIR;
2025-12-13 13:27:05 +00:00
/// Инициализация подключения к PostgreSQL
Future<AppDatabase> _initDatabase() async {
2025-12-11 20:57:26 +00:00
var attempt = 0;
2025-12-13 13:27:05 +00:00
const maxAttempts = 5;
while (attempt < maxAttempts) {
print('Attempt ${attempt + 1}/$maxAttempts to connect to PostgreSQL...');
try {
// Создать подключение из environment variables
final db = AppDatabase.fromEnvironment();
// Проверить подключение
await db.customSelect('SELECT 1').getSingle();
print('✅ Successfully connected to PostgreSQL');
return database = db;
} catch (e, s) {
print('❌ Error connecting to PostgreSQL: $e');
log('Error connecting to PostgreSQL: $e', error: e, stackTrace: s);
attempt++;
if (attempt < maxAttempts) {
final delay = Duration(seconds: attempt * 5);
print('Retrying in ${delay.inSeconds} seconds...');
await Future.delayed(delay);
}
}
2025-12-11 20:57:26 +00:00
}
2025-12-13 13:27:05 +00:00
throw Exception('Failed to connect to PostgreSQL after $maxAttempts attempts');
2025-12-11 20:57:26 +00:00
}
2025-12-11 17:49:15 +00:00
void main() async {
2025-12-13 13:27:05 +00:00
print('🚀 Starting Mnemo Cards Backend...');
// Читаем environment variables
final backupDir = Platform.environment['BACKUP_DIR'] ?? '../backups/';
2025-12-11 17:49:15 +00:00
WORK_DIR = Platform.environment['WORK_DIR'] ?? '/root/mnemo_cards_backend';
2025-12-13 13:27:05 +00:00
final debugMode = Platform.environment['DEBUG'] == 'true' ||
Platform.environment['DEBUG'] == '1';
print('📂 Working directory: $WORK_DIR');
print('🐛 Debug mode: $debugMode');
2025-11-16 11:25:27 +00:00
print(
'running server in ${(await Process.run('pwd', [], runInShell: true)).stdout}',
);
// For rustore payments
2025-12-13 14:48:00 +00:00
// final rustoreEnabled = false;
// if (rustoreEnabled) {
// final pythonInit = await Process.run(
// workingDirectory: WORK_DIR,
// './prepare_python.sh',
// [],
// runInShell: true,
// );
// print(pythonInit.stdout);
// print(pythonInit.stderr);
// } else {
// log('\n\n*******\nRUSTORE IS DISABLED\n******\n\n', level: 1000);
// }
2025-12-11 20:57:26 +00:00
2025-12-13 13:27:05 +00:00
// Инициализация PostgreSQL
try {
await _initDatabase();
// Регистрация в DI
getIt.registerSingleton<AppDatabase>(database);
// Настройка остальных зависимостей
configureDependencies();
// Запуск API сервера
print('🌐 Starting API server...');
await getIt<MnemoShelf>().initV2();
// Запуск cron jobs
print('⏰ Starting cron jobs...');
// ignore: unawaited_futures
CronManager([
DeleteOldArchives(),
2025-12-13 14:48:00 +00:00
CheckAdminsTask(database),
2025-12-13 13:27:05 +00:00
getIt.get<CheckPaymentTask>(),
2025-12-13 14:48:00 +00:00
AddFreePacks(getIt.get<FreePacksDistributor>(), database),
2025-12-13 13:27:05 +00:00
Backup(backupDir),
2025-12-13 14:48:00 +00:00
GeneratePromocodes(database),
DiscountCampaignTask(getIt.get<DiscountsManager>(), database),
2025-12-13 13:27:05 +00:00
UpdateOnlineUsersTask(getIt.get<UserManager>()),
2025-12-13 14:48:00 +00:00
TasksSeederTask(database),
2025-12-13 13:27:05 +00:00
]).init();
print('✅ Backend started successfully!');
} catch (e, s) {
print('❌ Fatal error starting backend: $e');
log('Fatal error starting backend: $e', error: e, stackTrace: s);
exit(1);
}
// Обработка SIGTERM для graceful shutdown
2025-12-11 20:50:30 +00:00
ProcessSignal.sigterm.watch().listen((signal) async {
2025-12-13 13:27:05 +00:00
print('🛑 Received SIGTERM, shutting down gracefully...');
2025-12-11 20:57:26 +00:00
try {
2025-12-13 13:27:05 +00:00
// Закрыть подключение к БД
await database.close();
print('✅ Database connection closed');
2025-12-11 20:57:26 +00:00
} catch (e, s) {
2025-12-13 13:27:05 +00:00
print('❌ Error closing database: $e');
log('Error closing database: $e', error: e, stackTrace: s);
2025-12-11 20:57:26 +00:00
}
2025-12-13 13:27:05 +00:00
2025-12-11 20:50:30 +00:00
exit(0);
});
2025-11-16 11:25:27 +00:00
}