Refactor database managers to use per-request connections

This commit is contained in:
Jonas
2025-11-21 23:15:26 +01:00
parent 5a2c53cb22
commit 18bf611eba
3 changed files with 143 additions and 92 deletions

View File

@@ -5,23 +5,28 @@ require("dotenv").config();
class DataBaseManager {
constructor(host, database) {
this.connection = mySql.createConnection({
this.connectionConfig = {
host: host,
port: process.env.DB_PORT || 3306,
user: "root",
password: process.env.DB_PASSWORD || undefined,
database: database
};
const connectionFactory = () => this.createConnection();
this.usermanager = new UserManager(connectionFactory);
this.scoremanager = new ScoreManager(connectionFactory);
}
createConnection() {
const connection = mySql.createConnection(this.connectionConfig);
connection.on("error", (error) => {
console.error("Database connection error:", error);
});
this.connection.connect((err) => {
if (err) {
throw err;
}
});
this.usermanager = new UserManager(this.connection);
this.scoremanager = new ScoreManager(this.connection);
return connection;
}
}

View File

@@ -2,42 +2,59 @@ const mySql = require("mysql2");
const Score = require("./Score");
class ScoreManager{
/**@param {mySql.Connection} connection*/
constructor(connection) {
this.connection = connection;
/**@param {() => mySql.Connection} connectionFactory*/
constructor(connectionFactory) {
this.connectionFactory = connectionFactory;
this.splitLimit = 25;
}
async getAllScores(){
const response = await this.connection.promise().query("SELECT * FROM scores ORDER BY score DESC");
const sortedScores = response[0].map((scoreData, index) => new Score(scoreData, index + 1));
async withConnection(callback) {
const connection = this.connectionFactory();
return sortedScores;
try {
return await callback(connection);
}
finally {
connection.end();
}
}
async getAllScores(){
return await this.withConnection(async (connection) => {
const response = await connection.promise().query("SELECT * FROM scores ORDER BY score DESC");
const sortedScores = response[0].map((scoreData, index) => new Score(scoreData, index + 1));
return sortedScores;
});
}
async createScore(newScoreJson){
const sql = "INSERT INTO scores (user1, user2, score) VALUES (?, ?, ?)";
return await this.withConnection(async (connection) => {
const sql = "INSERT INTO scores (user1, user2, score) VALUES (?, ?, ?)";
const insertResult = await this.connection
.promise()
.query(sql, [newScoreJson.user1, newScoreJson.user2, newScoreJson.score]);
const insertId = insertResult[0].insertId;
const insertResult = await connection
.promise()
.query(sql, [newScoreJson.user1, newScoreJson.user2, newScoreJson.score]);
const insertId = insertResult[0].insertId;
const selectSql = "SELECT * FROM scores WHERE id = ?";
const selectResult = await this.connection.promise().query(selectSql, [insertId]);
const selectSql = "SELECT * FROM scores WHERE id = ?";
const selectResult = await connection.promise().query(selectSql, [insertId]);
const rank = await this.getRankById(insertId);
const rank = await this.getRankById(insertId);
return new Score(selectResult[0][0], rank);
return new Score(selectResult[0][0], rank);
});
}
async getScoreById(id){
const response = await this.connection.promise().query("SELECT * FROM scores WHERE id = ?", [id]);
return await this.withConnection(async (connection) => {
const response = await connection.promise().query("SELECT * FROM scores WHERE id = ?", [id]);
const rank = await this.getRankById(id);
const rank = await this.getRankById(id);
return new Score(response[0][0], rank);
return new Score(response[0][0], rank);
});
}
async getSplitedScoreCount(){
@@ -51,26 +68,30 @@ class ScoreManager{
async getSpiltedScore(count){
const offset = (count - 1) * this.splitLimit;
const response = await this.connection.promise().query(
`SELECT * FROM scores ORDER BY score DESC LIMIT ${this.splitLimit} OFFSET ${offset}`,
);
return await this.withConnection(async (connection) => {
const response = await connection.promise().query(
`SELECT * FROM scores ORDER BY score DESC LIMIT ${this.splitLimit} OFFSET ${offset}`,
);
const sortedScoreSplit = response[0].map((scoreData, index) => {
const rank = offset + index + 1;
return new Score(scoreData, rank);
const sortedScoreSplit = response[0].map((scoreData, index) => {
const rank = offset + index + 1;
return new Score(scoreData, rank);
});
return sortedScoreSplit;
});
return sortedScoreSplit;
}
async getRankById(id){
const rankSql =
"SELECT COUNT(*) + 1 AS rank_position FROM scores WHERE score > (SELECT score FROM scores WHERE id = ?)";
const rankResult = await this.connection.promise().query(rankSql, [id]);
return await this.withConnection(async (connection) => {
const rankSql =
"SELECT COUNT(*) + 1 AS rank_position FROM scores WHERE score > (SELECT score FROM scores WHERE id = ?)";
const rankResult = await connection.promise().query(rankSql, [id]);
const rank = rankResult[0][0]?.rank_position ?? null;
const rank = rankResult[0][0]?.rank_position ?? null;
return rank;
return rank;
});
}
}

View File

@@ -3,9 +3,20 @@ const bcrypt = require("bcrypt")
const User = require("./User")
class UserManager {
/**@param {mySql.Connection} connection*/
constructor(connection) {
this.connection = connection;
/**@param {() => mySql.Connection} connectionFactory*/
constructor(connectionFactory) {
this.connectionFactory = connectionFactory;
}
async withConnection(callback) {
const connection = this.connectionFactory();
try {
return await callback(connection);
}
finally {
connection.end();
}
}
// Gebe zumindest {username: "x", password: "x"} mit!
@@ -16,14 +27,20 @@ class UserManager {
const user = await this.getUser({username: userJson.username});
if(user) return 0;
try {
const passHash = await bcrypt.hash(userJson.password, 10);
this.connection.query(`INSERT INTO users (username, email, password, fullName) VALUES ("${userJson.username}",` +
` ${userJson.email ? `"${userJson.email}"` : "NULL"}, "${passHash}", ${userJson.fullName ? `"${userJson.fullName}"` : "NULL"})`);
return 1;
} catch (error) {
console.log(error);
}
return await this.withConnection(async (connection) => {
try {
const passHash = await bcrypt.hash(userJson.password, 10);
await connection
.promise()
.query(
`INSERT INTO users (username, email, password, fullName) VALUES ("${userJson.username}",` +
` ${userJson.email ? `"${userJson.email}"` : "NULL"}, "${passHash}", ${userJson.fullName ? `"${userJson.fullName}"` : "NULL"})`
);
return 1;
} catch (error) {
console.log(error);
}
});
}
// Gebe nichts mit um alle user zu bekommen oder {id: 1} oder {username: "x"} um darauf einen bestimmten zu bekommen;
@@ -37,30 +54,32 @@ class UserManager {
selectionString = `SELECT * FROM users WHERE username="${userData.username}"`;
}
try {
const response = await this.connection.promise().query(selectionString);
return await this.withConnection(async (connection) => {
try {
const response = await connection.promise().query(selectionString);
if(response[0].length === 0){
return null;
if(response[0].length === 0){
return null;
}
else if(response[0].length === 1){
const x = response[0][0];
return new User(x);
}
else{
let userArray = [];
response[0].forEach(x => {
const user = new User(x);
userArray.push(user);
});
return userArray;
}
} catch (error) {
console.log(error);
}
else if(response[0].length === 1){
const x = response[0][0];
return new User(x);
}
else{
let userArray = [];
response[0].forEach(x => {
const user = new User(x);
userArray.push(user);
});
return userArray;
}
} catch (error) {
console.log(error);
}
});
}
// 0: User Existiert nicht | 1: Funktioniert
@@ -70,19 +89,23 @@ class UserManager {
if(!user) return 0;
if(!newUserData.password) return 0;
try {
this.connection.query(
`UPDATE users SET
return await this.withConnection(async (connection) => {
try {
await connection
.promise()
.query(
`UPDATE users SET
username="${newUserData.username}",
email=${newUserData.email ? `"${newUserData.email}"` : "NULL"},
fullName=${newUserData.fullName ? `"${newUserData.fullName}"` : "NULL"},
password="${newUserData.password}"
WHERE id = ${id}`
)
return 1;
} catch (error) {
console.log(error)
}
);
return 1;
} catch (error) {
console.log(error)
}
});
}
// 0: Es gibt den User nicht | 1: Funktioniert
@@ -90,12 +113,14 @@ class UserManager {
const user = await this.getUser({id});
if(!user) return 0;
try {
this.connection.query(`DELETE FROM users where id=${id}`);
return 1;
} catch (error) {
console.log(error)
}
return await this.withConnection(async (connection) => {
try {
await connection.promise().query(`DELETE FROM users where id=${id}`);
return 1;
} catch (error) {
console.log(error)
}
});
}
}