File size: 4,122 Bytes
cd7b281
 
 
 
 
 
 
8c3c2a2
cd7b281
 
 
 
 
 
8c3c2a2
cd7b281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c3c2a2
cd7b281
 
 
 
 
 
 
 
 
 
 
 
 
 
8c3c2a2
 
cd7b281
 
8c3c2a2
 
 
 
cd7b281
8c3c2a2
cd7b281
8c3c2a2
cd7b281
8c3c2a2
 
cd7b281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import express from 'express';
import cors from 'cors';
import cron from 'node-cron';
import { initializeDatabase, refreshData, searchByName } from './database.js';

// --- Константы ---
const PORT = process.env.PORT || 7860;
const API_VERSION = "1.4";

// --- Настройка приложения Express ---
const app = express();
app.use(cors());
app.use(express.json());

let isReady = false;

// --- Middleware для проверки готовности ---
app.use((req, res, next) => {
    if (!isReady && req.path !== '/health') {
        return res.status(503).json({ message: 'Сервис временно недоступен, идет инициализация данных.', statusCode: 503 });
    }
    next();
});

// --- API Эндпоинты ---
app.get('/health', (req, res) => {
    res.status(200).json({ status: isReady ? 'UP' : 'DOWN', message: isReady ? 'Сервис готов к работе' : 'Идет инициализация' });
});

app.get(`/v${API_VERSION}/movie/search`, async (req, res) => {
    const { query, page, limit } = req.query;

    if (!query) {
        return res.status(400).json({ message: 'Параметр "query" является обязательным.', statusCode: 400 });
    }

    const pageNum = parseInt(page, 10) || 1;
    const limitNum = Math.min(parseInt(limit, 10) || 10, 250);

    try {
        const { docs, total } = await searchByName(query, pageNum, limitNum);
        const pages = Math.ceil(total / limitNum);
        res.json({ docs, total, limit: limitNum, page: pageNum, pages });
    } catch (e) {
        console.error(`Ошибка при поиске по запросу "${query}":`, e);
        res.status(500).json({ message: 'Внутренняя ошибка сервера при поиске.', error: e.message });
    }
});

// --- Логика запуска сервера ---
(async () => {
    try {
        // ИСПРАВЛЕНИЕ: Получаем объект 'db' после инициализации.
        const db = await initializeDatabase();
        
        const needsRebuild = process.argv.includes('--rebuild-index');
        
        // ИСПРАВЛЕНИЕ: Используем полученный 'db' для запроса.
        const result = await db.get('SELECT COUNT(*) as count FROM movies');
        const moviesCount = result.count;

        if (needsRebuild || moviesCount === 0) {
            if (needsRebuild) console.log('Обнаружен флаг --rebuild-index. Запуск принудительной переиндексации.');
            if (moviesCount === 0) console.log('База данных пуста. Запуск первоначальной загрузки.');
            await refreshData();
        } else {
            console.log(`В базе уже есть ${moviesCount} фильмов. Запуск в штатном режиме.`);
        }

        isReady = true;
        console.log('✅ Сервис готов к приему запросов!');

        app.listen(PORT, () => {
            console.log(`🚀 Сервер поиска запущен на порту ${PORT}`);
            console.log(`URL для поиска: http://localhost:${PORT}/v${API_VERSION}/movie/search`);
        });

        cron.schedule('0 3 * * *', async () => {
            console.log('Начало планового ежедневного обновления данных...');
            isReady = false;
            try {
                await refreshData();
            } catch (error) {
                console.error('Критическая ошибка во время планового обновления:', error);
            }
            isReady = true;
            console.log('Плановое обновление завершено. Сервис снова готов к работе.');
        }, { scheduled: true, timezone: "Europe/Moscow" });

    } catch (e) {
        console.error("❌ Критическая ошибка при запуске сервера:", e);
        process.exit(1);
    }
})();