Merge pull request #6 from kobolol/codex/update-database-connection-handling
Refactor database connections to use per-query instances
This commit is contained in:
@@ -5,23 +5,28 @@ require("dotenv").config();
|
|||||||
|
|
||||||
class DataBaseManager {
|
class DataBaseManager {
|
||||||
constructor(host, database) {
|
constructor(host, database) {
|
||||||
this.connection = mySql.createConnection({
|
this.connectionConfig = {
|
||||||
host: host,
|
host: host,
|
||||||
port: process.env.DB_PORT || 3306,
|
port: process.env.DB_PORT || 3306,
|
||||||
user: "root",
|
user: "root",
|
||||||
password: process.env.DB_PASSWORD || undefined,
|
password: process.env.DB_PASSWORD || undefined,
|
||||||
database: database
|
database: database
|
||||||
});
|
};
|
||||||
|
|
||||||
this.connection.connect((err) => {
|
const connectionFactory = () => this.createConnection();
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
|
|
||||||
|
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.usermanager = new UserManager(this.connection);
|
return connection;
|
||||||
this.scoremanager = new ScoreManager(this.connection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,42 +2,59 @@ const mySql = require("mysql2");
|
|||||||
const Score = require("./Score");
|
const Score = require("./Score");
|
||||||
|
|
||||||
class ScoreManager{
|
class ScoreManager{
|
||||||
/**@param {mySql.Connection} connection*/
|
/**@param {() => mySql.Connection} connectionFactory*/
|
||||||
constructor(connection) {
|
constructor(connectionFactory) {
|
||||||
this.connection = connection;
|
this.connectionFactory = connectionFactory;
|
||||||
|
|
||||||
this.splitLimit = 25;
|
this.splitLimit = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async withConnection(callback) {
|
||||||
|
const connection = this.connectionFactory();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await callback(connection);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
connection.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getAllScores(){
|
async getAllScores(){
|
||||||
const response = await this.connection.promise().query("SELECT * FROM scores ORDER BY score DESC");
|
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));
|
const sortedScores = response[0].map((scoreData, index) => new Score(scoreData, index + 1));
|
||||||
|
|
||||||
return sortedScores;
|
return sortedScores;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createScore(newScoreJson){
|
async createScore(newScoreJson){
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
const sql = "INSERT INTO scores (user1, user2, score) VALUES (?, ?, ?)";
|
const sql = "INSERT INTO scores (user1, user2, score) VALUES (?, ?, ?)";
|
||||||
|
|
||||||
const insertResult = await this.connection
|
const insertResult = await connection
|
||||||
.promise()
|
.promise()
|
||||||
.query(sql, [newScoreJson.user1, newScoreJson.user2, newScoreJson.score]);
|
.query(sql, [newScoreJson.user1, newScoreJson.user2, newScoreJson.score]);
|
||||||
const insertId = insertResult[0].insertId;
|
const insertId = insertResult[0].insertId;
|
||||||
|
|
||||||
const selectSql = "SELECT * FROM scores WHERE id = ?";
|
const selectSql = "SELECT * FROM scores WHERE id = ?";
|
||||||
const selectResult = await this.connection.promise().query(selectSql, [insertId]);
|
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){
|
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(){
|
async getSplitedScoreCount(){
|
||||||
@@ -51,7 +68,8 @@ class ScoreManager{
|
|||||||
async getSpiltedScore(count){
|
async getSpiltedScore(count){
|
||||||
const offset = (count - 1) * this.splitLimit;
|
const offset = (count - 1) * this.splitLimit;
|
||||||
|
|
||||||
const response = await this.connection.promise().query(
|
return await this.withConnection(async (connection) => {
|
||||||
|
const response = await connection.promise().query(
|
||||||
`SELECT * FROM scores ORDER BY score DESC LIMIT ${this.splitLimit} OFFSET ${offset}`,
|
`SELECT * FROM scores ORDER BY score DESC LIMIT ${this.splitLimit} OFFSET ${offset}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -61,16 +79,19 @@ class ScoreManager{
|
|||||||
});
|
});
|
||||||
|
|
||||||
return sortedScoreSplit;
|
return sortedScoreSplit;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRankById(id){
|
async getRankById(id){
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
const rankSql =
|
const rankSql =
|
||||||
"SELECT COUNT(*) + 1 AS rank_position FROM scores WHERE score > (SELECT score FROM scores WHERE id = ?)";
|
"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]);
|
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;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,20 @@ const bcrypt = require("bcrypt")
|
|||||||
const User = require("./User")
|
const User = require("./User")
|
||||||
|
|
||||||
class UserManager {
|
class UserManager {
|
||||||
/**@param {mySql.Connection} connection*/
|
/**@param {() => mySql.Connection} connectionFactory*/
|
||||||
constructor(connection) {
|
constructor(connectionFactory) {
|
||||||
this.connection = connection;
|
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!
|
// Gebe zumindest {username: "x", password: "x"} mit!
|
||||||
@@ -16,14 +27,20 @@ class UserManager {
|
|||||||
const user = await this.getUser({username: userJson.username});
|
const user = await this.getUser({username: userJson.username});
|
||||||
if(user) return 0;
|
if(user) return 0;
|
||||||
|
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
try {
|
try {
|
||||||
const passHash = await bcrypt.hash(userJson.password, 10);
|
const passHash = await bcrypt.hash(userJson.password, 10);
|
||||||
this.connection.query(`INSERT INTO users (username, email, password, fullName) VALUES ("${userJson.username}",` +
|
await connection
|
||||||
` ${userJson.email ? `"${userJson.email}"` : "NULL"}, "${passHash}", ${userJson.fullName ? `"${userJson.fullName}"` : "NULL"})`);
|
.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;
|
return 1;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gebe nichts mit um alle user zu bekommen oder {id: 1} oder {username: "x"} um darauf einen bestimmten zu bekommen;
|
// Gebe nichts mit um alle user zu bekommen oder {id: 1} oder {username: "x"} um darauf einen bestimmten zu bekommen;
|
||||||
@@ -37,8 +54,9 @@ class UserManager {
|
|||||||
selectionString = `SELECT * FROM users WHERE username="${userData.username}"`;
|
selectionString = `SELECT * FROM users WHERE username="${userData.username}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
try {
|
try {
|
||||||
const response = await this.connection.promise().query(selectionString);
|
const response = await connection.promise().query(selectionString);
|
||||||
|
|
||||||
if(response[0].length === 0){
|
if(response[0].length === 0){
|
||||||
return null;
|
return null;
|
||||||
@@ -61,6 +79,7 @@ class UserManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0: User Existiert nicht | 1: Funktioniert
|
// 0: User Existiert nicht | 1: Funktioniert
|
||||||
@@ -70,19 +89,23 @@ class UserManager {
|
|||||||
if(!user) return 0;
|
if(!user) return 0;
|
||||||
if(!newUserData.password) return 0;
|
if(!newUserData.password) return 0;
|
||||||
|
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
try {
|
try {
|
||||||
this.connection.query(
|
await connection
|
||||||
|
.promise()
|
||||||
|
.query(
|
||||||
`UPDATE users SET
|
`UPDATE users SET
|
||||||
username="${newUserData.username}",
|
username="${newUserData.username}",
|
||||||
email=${newUserData.email ? `"${newUserData.email}"` : "NULL"},
|
email=${newUserData.email ? `"${newUserData.email}"` : "NULL"},
|
||||||
fullName=${newUserData.fullName ? `"${newUserData.fullName}"` : "NULL"},
|
fullName=${newUserData.fullName ? `"${newUserData.fullName}"` : "NULL"},
|
||||||
password="${newUserData.password}"
|
password="${newUserData.password}"
|
||||||
WHERE id = ${id}`
|
WHERE id = ${id}`
|
||||||
)
|
);
|
||||||
return 1;
|
return 1;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0: Es gibt den User nicht | 1: Funktioniert
|
// 0: Es gibt den User nicht | 1: Funktioniert
|
||||||
@@ -90,12 +113,14 @@ class UserManager {
|
|||||||
const user = await this.getUser({id});
|
const user = await this.getUser({id});
|
||||||
if(!user) return 0;
|
if(!user) return 0;
|
||||||
|
|
||||||
|
return await this.withConnection(async (connection) => {
|
||||||
try {
|
try {
|
||||||
this.connection.query(`DELETE FROM users where id=${id}`);
|
await connection.promise().query(`DELETE FROM users where id=${id}`);
|
||||||
return 1;
|
return 1;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user