-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.js
184 lines (151 loc) · 5.08 KB
/
database.js
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Importing the crypto module with ES6 syntax
import crypto from 'crypto';
import { promisify } from 'util';
import Log from "./logger.js";
import {existsSync, mkdirSync} from 'fs';
import sqlite3 from 'sqlite3';
import path from 'path';
import cron from 'node-cron';
sqlite3.verbose();
let requestMap = new Map();
let db = null;
// Function to create an MD5 hash
function createMD5Hash(input) {
const hash = crypto.createHash('md5');
hash.update(input);
return hash.digest('hex');
}
function key({concept="", space="", tool="", dataset="", type="", referer=""} = {}){
return createMD5Hash(`${concept} ${space} ${tool} ${dataset} ${referer} ${type}`);
}
const dbFilePath = path.resolve("./database/");
function ensurePathExists(){
if (!existsSync(dbFilePath)) mkdirSync(dbFilePath, { recursive: true });
}
export function init({filename = "events.db"} = {}){
// Path to the SQLite database file
ensurePathExists();
// Initialize SQLite database
return db = new sqlite3.Database(path.resolve(dbFilePath, filename), (err) => {
if (err) {
Log.error('Error opening database:', err.message);
} else {
// Create the table if it doesn't exist
db.run(`
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
concept TEXT,
space TEXT,
tool TEXT,
dataset TEXT,
type TEXT,
referer TEXT,
count INTEGER,
date DATE DEFAULT CURRENT_DATE
)
`);
Log.info('Connected to SQLite database.');
}
});
}
export async function getCount(){
// Promisify db.get() function
const getAsync = promisify(db.get).bind(db);
try {
const row = await getAsync("SELECT COUNT(*) as count FROM events");
console.log(`Number of rows in the events table: ${row.count}`);
return {eventsInDb: row.count, eventsInCache: requestMap.size};
} catch (err) {
console.error("Error counting rows:", err.message);
}
}
export function recordToCache(params = {}){
const k = key(params);
const now = new Date();
const now_ms = now.valueOf();
const record = requestMap.get(k);
if(!record) {
requestMap.set(k, {...params, count: 1, time: [now_ms]});
return 1;
} else {
record.count = record.count + 1;
record.time.push(now_ms);
return record.count;
}
}
export function retrieveAllFromCache(){
return [...requestMap.values()];
}
export function retrieveOneFromCache(params){
return requestMap.get(key(params));
}
export async function retrieveFromDb({concept, space, tool, dataset, type, referer, from_count, to_count, from_date, to_date} = {}){
let query = 'SELECT * FROM events WHERE 1=1';
const params = [];
if (concept) { query += ' AND concept = ?'; params.push(concept);}
if (space) { query += ' AND space = ?'; params.push(space);}
if (tool) { query += ' AND tool = ?'; params.push(tool);}
if (dataset) { query += ' AND dataset = ?'; params.push(dataset);}
if (type) { query += ' AND type = ?'; params.push(type);}
if (referer) { query += ' AND referer = ?'; params.push(referer);}
if (dataset) { query += ' AND dataset = ?'; params.push(dataset);}
if (from_date) { query += ' AND date >= ?'; params.push(from_date);}
if (to_date) { query += ' AND date <= ?'; params.push(to_date);}
if (from_count) { query += ' AND count >= ?'; params.push(from_count);}
if (to_count) { query += ' AND count <= ?'; params.push(to_count);}
return new Promise((resolve, reject) => {
db.all(query, params, (err, rows) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
}
export function saveToDb() {
const events = [...requestMap.values()];
// Start the transaction
db.serialize(() => {
db.run('BEGIN TRANSACTION');
const stmt = db.prepare('INSERT INTO events (concept, space, tool, dataset, type, referer, count) VALUES (?, ?, ?, ?, ?, ?, ?)');
// Insert each event in the array
events.forEach(({concept, space, tool, dataset, type, referer, count}) => {
stmt.run(concept, space, tool, dataset, type, referer, count);
});
// Finalize the prepared statement and commit the transaction
stmt.finalize();
db.run('COMMIT');
requestMap = new Map();
});
}
export function erase() {
return new Promise((resolve, reject) => {
requestMap = new Map();
db.run("DELETE FROM events", function(err) {
if (err) {
Log.error(err.message)
reject(err);
} else {
Log.info(`All rows deleted from the events table`);
resolve()
}
});
})
}
// Every hour at minute 0
//cron.schedule('0 * * * *', () => backupEvents());
// Every day at 23:59
cron.schedule('59 23 * * *', () => saveToDb());
process.on('SIGINT', () => {
db.close(() => {
Log.info('Database connection closed.');
process.exit(0);
});
});
process.on('SIGTERM', () => {
db.close(() => {
Log.info('Database connection closed.');
process.exit(0);
});
});