diff --git a/.env.example b/.env.example index 2661515..fbe7d6a 100644 --- a/.env.example +++ b/.env.example @@ -4,12 +4,15 @@ # Application port APP_PORT=3000 -# Database type: either 'sqlite' or 'mongodb' +# Database type: either 'sqlite' or 'mongodb' or 'mysql' DB_TYPE=sqlite # If using MongoDB, provide the connection string # DB_URL=mongodb://127.0.0.1:27017 +# If using MySQL, provide the connection string +# DB_URL=mysql://127.0.0.1:3306/dbname?user=root&password=root + # Database write interval in seconds (0 for real-time) DB_INTERVAL=60 diff --git a/db/index.js b/db/index.js index efcdfb6..25273aa 100644 --- a/db/index.js +++ b/db/index.js @@ -6,6 +6,12 @@ switch(process.env.DB_TYPE){ case 'mongodb': db = require('./mongodb') break; + case 'redis': + db = require('./redis') + break; + case 'mysql': + db = require('./mysql') + break; case 'sqlite': default: db = require('./sqlite') diff --git a/db/mysql.js b/db/mysql.js new file mode 100644 index 0000000..ee1ee99 --- /dev/null +++ b/db/mysql.js @@ -0,0 +1,48 @@ +"use strict"; + +const mysql = require('mysql2/promise'); + +// the default mysql url (local server) +const mysqlURL = process.env.DB_URL || "mysql://localhost:3306/counter"; + +let connection; + + + +async function initDb() { + connection = await mysql.createConnection(mysqlURL); + await connection.execute("CREATE TABLE IF NOT EXISTS tb_count (name VARCHAR(32) NOT NULL, num INT NOT NULL, PRIMARY KEY (name)) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); +} + +async function getNum(name) { + const [rows] = await connection.execute("SELECT num FROM tb_count WHERE name = ?", [name]); + console.log(rows) + return rows[0]; +} + +async function getAll() { + const [rows] = await connection.execute("SELECT * FROM tb_count"); + console.log(rows) + return rows; +} + +async function setNum(name, num) { + connection.execute("INSERT INTO tb_count (name, num) VALUES (?, ?) ON DUPLICATE KEY UPDATE num = ?", [name, num, num]); +// await connection.execute("INSERT INTO tb_count (name, num) VALUES (?, ?) ON DUPLICATE KEY UPDATE num = ?", [name, num, num]); +} + +async function setNumMulti(counters) { + for (let counter of counters) { + setNum(counter.name, counter.num); + // await setNum(counter.name, counter.num); + } +} + +initDb(); + +module.exports = { + getNum, + getAll, + setNum, + setNumMulti, +}; diff --git a/db/redis.js b/db/redis.js new file mode 100644 index 0000000..b96ec11 --- /dev/null +++ b/db/redis.js @@ -0,0 +1,43 @@ +"use strict"; + +const Redis = require("ioredis"); + +// the default redis url (local server) +const redisURL = process.env.DB_URL || "redis://127.0.0.1:6379"; +const redisPrefix = process.env.REDIS_PREFIX || "moe_count_" + +const redis = new Redis(redisURL); + +async function getNum(name) { + const result = await redis.get(redisPrefix+name) + if(result === null || isNaN(result) ){ + return {name:name,num:0} + } + return {name:name,num:parseInt(result)} +} + + +async function getAll() { + const keys = await redis.keys(redisPrefix+'*'); + const values = await redis.mget(keys); + return keys.map((key, i) => ({ name: key, num: values[i] || 0 })) +} + +async function setNum(name, num) { + return redis.set(redisPrefix+name, num); +} + +async function setNumMulti(counters) { + const pipeline = redis.pipeline() + counters.forEach(({ name, num }) => { + pipeline.set(redisPrefix+name, num) + }) + await pipeline.exec() +} + +module.exports = { + getNum, + getAll, + setNum, + setNumMulti, +}; diff --git a/package.json b/package.json index 83187aa..40e0fb4 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,10 @@ "dotenv": "^16.4.5", "express": "^4.18.2", "image-size": "^0.8.3", + "ioredis": "^5.4.1", "mime-types": "^2.1.27", "mongoose": "^5.9.28", + "mysql2": "^3.11.5", "pug": "^3.0.0", "zod": "^3.23.8" },