errsole-mysql
Advanced tools
Comparing version 2.0.0 to 2.1.0
165
lib/index.js
/** | ||
* @typedef {Object} Log | ||
* @property {number} [id] | ||
* @property {number} [errsole_id] | ||
* @property {Date} timestamp | ||
* @property {string} hostname | ||
* @property {number} pid | ||
* @property {string} source | ||
* @property {Date} timestamp | ||
* @property {string} level | ||
@@ -15,9 +15,9 @@ * @property {string} message | ||
* @typedef {Object} LogFilter | ||
* @property {string[]} [hostnames] | ||
* @property {{source: string, level: string}[]} [level_json] | ||
* @property {number} [errsole_id] | ||
* @property {number} [lt_id] | ||
* @property {number} [gt_id] | ||
* @property {number} [errsole_id] | ||
* @property {Date} [lte_timestamp] | ||
* @property {Date} [gte_timestamp] | ||
* @property {string[]} [hostnames] | ||
* @property {{source: string, level: string}[]} [level_json] | ||
* @property {number} [limit=100] | ||
@@ -41,2 +41,12 @@ */ | ||
/** | ||
* @typedef {Object} Notification | ||
* @property {number} [id] | ||
* @property {number} [errsole_id] | ||
* @property {string} hostname | ||
* @property {string} hashed_message | ||
* @property {Date} [created_at] | ||
* @property {Date} [updated_at] | ||
*/ | ||
const bcrypt = require('bcryptjs'); | ||
@@ -71,3 +81,6 @@ const { EventEmitter } = require('events'); | ||
setInterval(() => this.flushLogs(), this.flushInterval); | ||
cron.schedule('0 * * * *', () => this.deleteExpiredLogs()); | ||
cron.schedule('0 * * * *', () => { | ||
this.deleteExpiredLogs(); | ||
this.deleteExpiredNotificationItems(); | ||
}); | ||
} | ||
@@ -138,2 +151,12 @@ | ||
\`value\` VARCHAR(255) NOT NULL | ||
)`, | ||
`CREATE TABLE IF NOT EXISTS \`errsole_notifications\` ( | ||
\`id\` BIGINT PRIMARY KEY AUTO_INCREMENT, | ||
\`errsole_id\` BIGINT, | ||
\`hostname\` VARCHAR(255), | ||
\`hashed_message\` VARCHAR(255), | ||
\`created_at\` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3), | ||
\`updated_at\` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), | ||
INDEX (\`hostname\`, \`hashed_message\`, \`created_at\`), | ||
INDEX (\`created_at\`) | ||
)` | ||
@@ -575,2 +598,132 @@ ]; | ||
/** | ||
* Inserts a notification, counts today's notifications, and retrieves the previous notification. | ||
* @param {Notification} notification - The notification to be inserted. | ||
* @returns {Promise<Object>} - Returns today's notification count and the previous notification. | ||
*/ | ||
async insertNotificationItem (notification = {}) { | ||
const errsoleId = notification.errsole_id; | ||
const hostname = notification.hostname; | ||
const hashedMessage = notification.hashed_message; | ||
const connection = await new Promise((resolve, reject) => { | ||
this.pool.getConnection((err, connection) => { | ||
if (err) return reject(err); | ||
resolve(connection); | ||
}); | ||
}); | ||
try { | ||
await new Promise((resolve, reject) => { | ||
connection.beginTransaction((err) => { | ||
if (err) return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
const fetchPreviousNotificationQuery = ` | ||
SELECT * FROM errsole_notifications | ||
WHERE hostname = ? AND hashed_message = ? | ||
ORDER BY created_at DESC | ||
LIMIT 1; | ||
`; | ||
const previousNotificationItem = await new Promise((resolve, reject) => { | ||
connection.query(fetchPreviousNotificationQuery, [hostname, hashedMessage], (err, results) => { | ||
if (err) return reject(err); | ||
resolve(results[0] || null); | ||
}); | ||
}); | ||
const insertNotificationQuery = ` | ||
INSERT INTO errsole_notifications (hostname, errsole_id, hashed_message) | ||
VALUES (?, ?, ?); | ||
`; | ||
await new Promise((resolve, reject) => { | ||
connection.query(insertNotificationQuery, [hostname, errsoleId, hashedMessage], (err) => { | ||
if (err) return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
const startOfDayUTC = new Date(); | ||
startOfDayUTC.setUTCHours(0, 0, 0, 0); | ||
const endOfDayUTC = new Date(); | ||
endOfDayUTC.setUTCHours(23, 59, 59, 999); | ||
const countTodayNotificationsQuery = ` | ||
SELECT COUNT(*) AS notificationCount | ||
FROM errsole_notifications | ||
WHERE hashed_message = ? AND created_at BETWEEN ? AND ?; | ||
`; | ||
const todayNotificationCount = await new Promise((resolve, reject) => { | ||
connection.query(countTodayNotificationsQuery, [hashedMessage, startOfDayUTC, endOfDayUTC], (err, result) => { | ||
if (err) return reject(err); | ||
resolve(result[0].notificationCount); | ||
}); | ||
}); | ||
await new Promise((resolve, reject) => { | ||
connection.commit((err) => { | ||
if (err) return reject(err); | ||
resolve(); | ||
}); | ||
}); | ||
return { | ||
previousNotificationItem, | ||
todayNotificationCount | ||
}; | ||
} catch (err) { | ||
await new Promise((resolve) => { | ||
connection.rollback(() => resolve()); | ||
}); | ||
throw err; | ||
} finally { | ||
connection.release(); | ||
} | ||
} | ||
/** | ||
* Deletes expired notifications based on TTL configuration. | ||
* | ||
* @async | ||
* @function deleteExpiredNotificationItems | ||
*/ | ||
async deleteExpiredNotificationItems () { | ||
if (this.deleteExpiredNotificationItemsRunning) return; | ||
this.deleteExpiredNotificationItemsRunning = true; | ||
const DEFAULT_NOTIFICATIONS_TTL = 30 * 24 * 60 * 60 * 1000; // 30 days in milliseconds | ||
try { | ||
let notificationsTTL = DEFAULT_NOTIFICATIONS_TTL; | ||
const configResult = await this.getConfig('logsTTL'); | ||
if (configResult.item) { | ||
const parsedTTL = parseInt(configResult.item.value, 10); | ||
notificationsTTL = isNaN(parsedTTL) ? DEFAULT_NOTIFICATIONS_TTL : parsedTTL; | ||
} | ||
let expirationTime = new Date(Date.now() - notificationsTTL); | ||
expirationTime = new Date(expirationTime).toISOString().slice(0, 19).replace('T', ' '); | ||
let deletedRowCount; | ||
do { | ||
deletedRowCount = await new Promise((resolve, reject) => { | ||
this.pool.query( | ||
'DELETE FROM errsole_notifications WHERE created_at < ? LIMIT 1000', | ||
[expirationTime], | ||
(err, results) => { | ||
if (err) return reject(err); | ||
resolve(results.affectedRows); | ||
} | ||
); | ||
}); | ||
await new Promise(resolve => setTimeout(resolve, 10000)); | ||
} while (deletedRowCount > 0); | ||
} catch (err) { | ||
console.error(err); | ||
} finally { | ||
this.deleteExpiredNotificationItemsRunning = false; | ||
} | ||
} | ||
/** | ||
* Creates a new user record in the database. | ||
@@ -577,0 +730,0 @@ * |
{ | ||
"name": "errsole-mysql", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "MySQL storage plugin for Errsole", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -44,2 +44,11 @@ declare module 'errsole-mysql' { | ||
interface Notification { | ||
id?: number; | ||
errsole_id: number; | ||
hostname: string; | ||
hashed_message: string; | ||
created_at?: Date; | ||
updated_at?: Date; | ||
} | ||
class ErrsoleMySQL { | ||
@@ -66,2 +75,5 @@ constructor(options: PoolOptions); | ||
deleteUser(userId: number): Promise<{}>; | ||
insertNotificationItem(notification: Notification): Promise<{ previousNotificationItem: Notification | null, todayNotificationCount: number }>; | ||
} | ||
@@ -68,0 +80,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
35830
916