80 lines
3.1 KiB
JavaScript
80 lines
3.1 KiB
JavaScript
const Database = require("./database");
|
|
|
|
/**
|
|
* Check if an error is specifically from a database operation
|
|
* This is more restrictive to avoid false positives (e.g., notification send failures)
|
|
* @param {Error} error The error to check
|
|
* @returns {boolean} True if this is a database error
|
|
*/
|
|
function isDatabaseError(error) {
|
|
if (!error) {
|
|
return false;
|
|
}
|
|
|
|
// Check for MySQL/MariaDB specific error codes (most reliable indicator)
|
|
if (
|
|
error.code &&
|
|
(error.code.startsWith("ER_") || // MySQL/MariaDB error codes
|
|
error.code === "PROTOCOL_CONNECTION_LOST" ||
|
|
error.code === "PROTOCOL_ENQUEUE_AFTER_QUIT" ||
|
|
error.code === "PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR")
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Check if error originated from database operations by examining stack trace
|
|
const stack = error.stack || "";
|
|
const isFromDatabaseCode =
|
|
stack.includes("redbean-node") ||
|
|
stack.includes("/server/database.js") ||
|
|
(stack.includes("/server/model/") && (stack.includes("R.") || stack.includes("knex")));
|
|
|
|
// For connection errors, only consider them database errors if:
|
|
// 1. They're from database code (stack trace check above), AND
|
|
// 2. They match database connection patterns
|
|
if (isFromDatabaseCode) {
|
|
// Check for connection errors that could be database-related
|
|
if (
|
|
error.code &&
|
|
(error.code === "EHOSTUNREACH" ||
|
|
error.code === "ECONNREFUSED" ||
|
|
error.code === "ETIMEDOUT" ||
|
|
error.code === "ENOTFOUND")
|
|
) {
|
|
// For MariaDB/MySQL, verify it's connecting to the actual database host/port
|
|
if (Database.dbConfig && Database.dbConfig.type && Database.dbConfig.type.endsWith("mariadb")) {
|
|
const dbPort = Database.dbConfig.port || 3306;
|
|
const dbHost = Database.dbConfig.hostname;
|
|
// Only match if port matches database port OR address matches database hostname
|
|
if ((error.port && error.port === dbPort) || (error.address && error.address === dbHost)) {
|
|
return true;
|
|
}
|
|
}
|
|
// For SQLite, connection errors from database code are database errors
|
|
if (Database.dbConfig && Database.dbConfig.type === "sqlite" && error.syscall === "connect") {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check for database-specific error messages (only if from database code)
|
|
if (
|
|
error.message &&
|
|
(error.message.includes("SQLITE_") ||
|
|
error.message.includes("SQLITE_ERROR") ||
|
|
error.message.includes("SQLITE_BUSY") ||
|
|
error.message.includes("SQLITE_LOCKED") ||
|
|
error.message.includes("database is locked") ||
|
|
error.message.includes("no such table") ||
|
|
(error.message.includes("Connection lost") && stack.includes("mysql")))
|
|
) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
module.exports = {
|
|
isDatabaseError,
|
|
};
|