@clarabellerising Какие именно дополнительные проверки на внешний IP (IPv4 и IPv6) вы хотите, чтобы я отключил?
Асинхронная функция зависает в связке с node.js
-
Приветствую!
Подскажите пожалуйста что может быть?
Есть Поток 1 в нем вызываю асинхронную функцию, а в ней есть код написан на node.js
когда выполняется этот код, зависает основной поток. Но результат я получаю но в моменте выполнения висит поток 1 а потом крашиться..
Версия BAS 28.1.2 версия Node.js v22.11.0
Большое спасибо за ответы или советы!const fs = require("fs").promises; const path = require("path"); const encoding = require("encoding"); const { MongoClient } = require("mongodb"); const crypto = require("crypto"); // Импортируем функцию для подключения к базе данных const getConnect = require("../connectDB"); // Конфигурационные параметры const MONGOSERVER = process.env.MONGOSERVER || [[MONGOSERVER]]; const DATABASE = process.env.DATABASE || [[DATABASE]]; const PATCHCRONAS_BASE = process.env.PATCHCRONAS_BASE || [[PATCHCRONAS]]; const SESSION_ID = process.env.SESSION_ID || [[SESSION_ID]]; const PATCHCRONAS = path.join(PATCHCRONAS_BASE, "out", SESSION_ID); const folderPath = path.join(PATCHCRONAS, `${SESSION_ID}_files`); const filePath = path.join(PATCHCRONAS, `${SESSION_ID}.txt`); /** * Асинхронно ожидает появления файла в течение заданного таймаута. * @param {string} filePath - Полный путь к файлу. * @param {number} timeout - Таймаут в миллисекундах. * @param {number} pollInterval - Интервал проверки в миллисекундах. * @returns {Promise<string>} - Возвращает путь к файлу, если он появляется вовремя. * @throws {Error} - Если файл не появляется в течение таймаута. */ async function waitForFile(filePath, timeout = 5 * 60 * 1000, pollInterval = 1000) { return new Promise((resolve, reject) => { const startTime = Date.now(); const interval = setInterval(async () => { try { await fs.access(filePath); clearInterval(interval); resolve(filePath); } catch (err) { if (Date.now() - startTime > timeout) { clearInterval(interval); reject(new Error("Файл не появился в течение 5 минут.")); } // Файл ещё не существует, продолжаем ожидание } }, pollInterval); }); } /** * Сохраняет HTML-контент в базу данных MongoDB. * @param {string} sessionId - Идентификатор сессии. * @param {string} sectionName - Название секции. * @param {string} htmlContent - HTML-содержимое. */ async function saveToDatabase(sessionId, sectionName, htmlContent) { try { const client = await getConnect(MONGOSERVER); const database = client.db(DATABASE); await database.collection("reports").findOneAndUpdate( { sessionId }, { $push: { sections: { name: sectionName, htmlContent, hasData: true, }, }, $set: { updatedAt: new Date() }, }, { returnDocument: "after", upsert: true } ); await client.close(); } catch (error) { console.error("Ошибка при сохранении данных в базу:", error.message); } } /** * Вычисляет SHA-256 хэш файла асинхронно. * @param {string} filePath - Путь к файлу. * @returns {Promise<string|null>} - Возвращает хэш или null в случае ошибки. */ async function getFileHash(filePath) { try { const fileBuffer = await fs.readFile(filePath); const hashSum = crypto.createHash("sha256"); hashSum.update(fileBuffer); return hashSum.digest("hex"); } catch { return null; } } /** * Извлекает имена файлов изображений из текста. * @param {string} text - Входной текст. * @returns {string[]} - Массив имен файлов изображений. */ function extractImageFilenames(text) { const pattern = /Cro[A-Za-z0-9]{2,7}\.(jpg|png)/gi; return text.match(pattern) || []; } /** * Удаляет дубликаты изображений по хэшу асинхронно. * @param {string[]} imageFilenames - Имена файлов изображений. * @param {string} folderPath - Путь к папке с изображениями. * @returns {Promise<number>} - Количество удалённых дубликатов. */ async function removeDuplicateImagesInOrder(imageFilenames, folderPath) { const imageHashes = new Map(); let duplicatesRemoved = 0; for (const fileName of imageFilenames) { const filePath = path.join(folderPath, fileName); try { await fs.access(filePath); } catch { continue; // Файл не существует } const fileHash = await getFileHash(filePath); if (!fileHash) continue; if (imageHashes.has(fileHash)) { try { await fs.unlink(filePath); duplicatesRemoved++; } catch (err) { console.error(`Не удалось удалить файл ${filePath}:`, err.message); } } else { imageHashes.set(fileHash, fileName); } } return duplicatesRemoved; } /** * Заменяет имена файлов изображений в тексте на встроенные изображения в формате base64. * @param {string} inputText - Входной текст. * @param {string} folderPath - Путь к папке с изображениями. * @returns {string} - Обработанный текст с встроенными изображениями. */ async function replaceImagesInText(inputText, folderPath) { let text = inputText; const pattern = /Cro[A-Za-z0-9]{2,7}\.(jpg|png)/gi; const matches = text.match(pattern); if (!matches) return text; for (const fileName of matches) { const filePath = path.join(folderPath, fileName); try { await fs.access(filePath); const fileBuffer = await fs.readFile(filePath); const base64Data = fileBuffer.toString("base64"); const mimeType = fileName.endsWith(".png") ? "image/png" : "image/jpeg"; const imgTag = `<div class="photo-container"><img src="data:${mimeType};base64,${base64Data}" alt="${fileName}"></div>`; const regex = new RegExp(fileName, "g"); text = text.replace(regex, imgTag); } catch { // Удаляем строку с отсутствующим изображением const regex = new RegExp(`.*${fileName}.*\n?`, "gi"); text = text.replace(regex, ""); } } return text; } /** * Получает MIME-тип файла по расширению. * @param {string} filePath - Путь к файлу. * @returns {string} - MIME-тип файла. */ function getMimeType(filePath) { const ext = path.extname(filePath).toLowerCase(); switch (ext) { case ".jpg": case ".jpeg": return "image/jpeg"; case ".png": return "image/png"; default: return "application/octet-stream"; } } /** * Очищает и форматирует текст. * @param {string} inputText - Входной текст. * @returns {string} - Очищенный и отформатированный текст. */ function cleanText(inputText) { let cleanedText = inputText .replace(/[-]/g, "") .replace(/[ \t]+/g, " ") .replace(/ *\n */g, "\n") .replace(/\n{2,}/g, "\n") .trim(); const photosLinePattern = /(^|\n)\s*Фото:\s*(\n|$)/gi; cleanedText = cleanedText.replace(photosLinePattern, ""); cleanedText = cleanedText.replace(/Ответ № (\d+)/g, "Лок № $1"); const lines = cleanedText.split("\n"); const uniqueLines = []; lines.forEach((line, index) => { const currentLine = line.trim().toLowerCase(); const previousLine = index > 0 ? lines[index - 1].trim().toLowerCase() : null; if (index === 0 || currentLine !== previousLine) { uniqueLines.push(line); } }); return uniqueLines.join("<br>"); } /** * Обрабатывает текст и изображения, а затем сохраняет результаты в базу данных. * @param {string} inputText - Входной текст. * @param {string} folderPath - Путь к папке с изображениями. * @param {string} sessionId - Идентификатор сессии. */ async function processTextAndImagesToDatabase(inputText, folderPath, sessionId) { try { const cleanedText = cleanText(inputText); const imageFilenames = extractImageFilenames(inputText); const folderExists = await fs.access(folderPath).then(() => true).catch(() => false); if (folderExists) { const duplicatesRemoved = await removeDuplicateImagesInOrder(imageFilenames, folderPath); console.log(`Удалено ${duplicatesRemoved} дубликатов изображений.`); } const finalText = await replaceImagesInText(cleanedText, folderPath); const htmlContent = ` <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Отчет</title> <style> body { font-family: Arial, sans-serif; line-height: 1.6; } .photo-container { margin: 10px 0; } .photo-container img { max-width: 100%; height: auto; display: block; } </style> </head> <body> ${finalText} </body> </html> `; await saveToDatabase(sessionId, "cas", htmlContent); console.log("Данные успешно сохранены в базу данных."); } catch (error) { console.error("Ошибка обработки текста и изображений:", error.message); } } /** * Основная функция обработки. */ async function main() { try { console.log("Ожидание появления файла..."); await waitForFile(filePath); console.log("Файл обнаружен."); // Читаем файл как Buffer const fileBuffer = await fs.readFile(filePath); // Конвертация из Windows-1251 в UTF-8 const convertedContent = encoding.convert(fileBuffer, "UTF-8", "WINDOWS-1251").toString(); // Перезаписываем файл уже в UTF-8 (опционально, если необходимо) await fs.writeFile(filePath, convertedContent, "utf8"); console.log("Файл успешно прочитан и преобразован."); // Обрабатываем текст и изображения, сохраняем в базу данных await processTextAndImagesToDatabase(convertedContent, folderPath, SESSION_ID); } catch (err) { console.error("Ошибка при обработке файла:", err.message); } } // Запуск основной функции main();