Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (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
143 lines
4.6 KiB
Dart
143 lines
4.6 KiB
Dart
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';
|
|
import 'package:mnemo_cards_backend/database/database.dart';
|
|
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';
|
|
|
|
late AppDatabase database;
|
|
|
|
late final String WORK_DIR;
|
|
|
|
/// Инициализация подключения к PostgreSQL
|
|
Future<AppDatabase> _initDatabase() async {
|
|
var attempt = 0;
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
throw Exception('Failed to connect to PostgreSQL after $maxAttempts attempts');
|
|
}
|
|
|
|
void main() async {
|
|
print('🚀 Starting Mnemo Cards Backend...');
|
|
|
|
// Читаем environment variables
|
|
final backupDir = Platform.environment['BACKUP_DIR'] ?? '../backups/';
|
|
WORK_DIR = Platform.environment['WORK_DIR'] ?? '/root/mnemo_cards_backend';
|
|
final debugMode = Platform.environment['DEBUG'] == 'true' ||
|
|
Platform.environment['DEBUG'] == '1';
|
|
|
|
print('📂 Working directory: $WORK_DIR');
|
|
print('🐛 Debug mode: $debugMode');
|
|
|
|
print(
|
|
'running server in ${(await Process.run('pwd', [], runInShell: true)).stdout}',
|
|
);
|
|
|
|
// For rustore payments
|
|
// 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);
|
|
// }
|
|
|
|
// Инициализация PostgreSQL
|
|
try {
|
|
await _initDatabase();
|
|
|
|
// Настройка зависимостей (AppDatabase уже регистрируется через @singleton в modules.dart)
|
|
configureDependencies();
|
|
|
|
// Запуск API сервера
|
|
print('🌐 Starting API server...');
|
|
await getIt<MnemoShelf>().initV2();
|
|
|
|
// Запуск cron jobs
|
|
print('⏰ Starting cron jobs...');
|
|
// ignore: unawaited_futures
|
|
CronManager([
|
|
DeleteOldArchives(),
|
|
CheckAdminsTask(database),
|
|
getIt.get<CheckPaymentTask>(),
|
|
AddFreePacks(getIt.get<FreePacksDistributor>(), database),
|
|
Backup(backupDir),
|
|
GeneratePromocodes(database),
|
|
DiscountCampaignTask(getIt.get<DiscountsManager>(), database),
|
|
UpdateOnlineUsersTask(getIt.get<UserManager>()),
|
|
TasksSeederTask(database),
|
|
TestGeneratorTask(getIt.get<TestManager>(), database),
|
|
]).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
|
|
ProcessSignal.sigterm.watch().listen((signal) async {
|
|
print('🛑 Received SIGTERM, shutting down gracefully...');
|
|
|
|
try {
|
|
// Закрыть подключение к БД
|
|
await database.close();
|
|
print('✅ Database connection closed');
|
|
} catch (e, s) {
|
|
print('❌ Error closing database: $e');
|
|
log('Error closing database: $e', error: e, stackTrace: s);
|
|
}
|
|
|
|
exit(0);
|
|
});
|
|
}
|