# ClosetManager-Back-end **Repository Path**: bug0101/closet-manager-back-end ## Basic Information - **Project Name**: ClosetManager-Back-end - **Description**: closetManager项目的后端,基于node.js+express实现 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-22 - **Last Updated**: 2025-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 使用 Redis 实现延迟队列(以 Node.js 为例)通常需要以下核心文件和依赖,以下是文件结构和内容说明: ### **一、项目根目录文件** #### **1. `package.json`(依赖管理)** ```json { "name": "redis-delay-queue-demo", "version": "1.0.0", "dependencies": { "bull": "^4.17.1", // 队列管理库(基于 Redis) "ioredis": "^5.3.2", // Redis 客户端(推荐) "express": "^4.18.2", // Web 框架(可选,用于接口演示) "mysql": "^2.3.3" // 数据库驱动(示例中使用 MySQL,可替换为其他数据库) }, "scripts": { "start": "node app.js", // 启动服务端 "worker": "node worker.js" // 启动队列消费者 } } ``` #### **2. `.env`(环境变量配置,可选)** 用于存储敏感信息(如 Redis 密码、数据库连接信息): ```env REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= DB_HOST=localhost DB_USER=root DB_PASSWORD= DB_DATABASE=test ``` ### **二、核心功能文件** #### **1. `redis-client.js`(Redis 连接配置)** ```javascript const Redis = require('ioredis'); require('dotenv').config(); // 加载环境变量(需先安装 dotenv) const redisClient = new Redis({ host: process.env.REDIS_HOST || 'localhost', port: process.env.REDIS_PORT || 6379, password: process.env.REDIS_PASSWORD || '', }); // 测试连接 redisClient.on('connect', () => { console.log('已连接到 Redis 服务器'); }); redisClient.on('error', (err) => { console.error('Redis 连接失败:', err); }); module.exports = redisClient; ``` #### **2. `queue.js`(队列定义与任务处理)** ```javascript const { Queue } = require('bull'); const redisClient = require('./redis-client'); const db = require('./db'); // 数据库连接模块(见下文) // 创建队列(队列名称可自定义,如 "reminderQueue") const reminderQueue = new Queue('reminderQueue', { redis: redisClient, }); // 定义任务处理逻辑(消费者) reminderQueue.process(async (job) => { const { content, userId } = job.data; console.log(`开始处理任务:${job.id},内容:${content}`); // 执行数据库操作(示例:插入提醒记录) const sql = 'INSERT INTO reminder (content, user_id) VALUES (?, ?)'; const [results] = await db.pool.query(sql, [content, userId]); if (results.affectedRows !== 1) { throw new Error('数据库插入失败'); } console.log('任务执行成功'); return results; }); // 错误处理:任务失败时触发 reminderQueue.on('failed', (job, error) => { console.error(`任务 ${job.id} 失败:`, error.message); // 可在此处添加重试逻辑或通知机制 }); module.exports = { reminderQueue }; ``` #### **3. `db.js`(数据库连接配置,以 MySQL 为例)** ```javascript const mysql = require('mysql2/pool'); require('dotenv').config(); const db = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, connectionLimit: 10, // 连接池最大连接数 }); module.exports = { pool: db, }; ``` #### **4. `routes.js`(接口路由,可选)** 用于接收前端请求并添加延迟任务(需配合 Express 框架): ```javascript const express = require('express'); const router = express.Router(); const { reminderQueue } = require('./queue'); // 添加延迟任务的接口 router.post('/add-delayed-reminder', async (req, res) => { const { content } = req.body; if (!content) { return res.status(400).json({ error: '内容不能为空' }); } try { // 添加任务到队列,延迟 40 分钟(2400000 毫秒) const job = await reminderQueue.add( { content, userId: req.user?.id || 1 // 示例用户 ID,实际需从认证获取 }, { delay: 40 * 60 * 1000, // 延迟时间(毫秒) attempts: 3, // 失败重试次数 removeOnComplete: true // 任务完成后自动删除 } ); res.json({ success: true, message: '任务已安排', jobId: job.id, }); } catch (error) { console.error('添加任务失败:', error); res.status(500).json({ error: '服务器内部错误' }); } }); module.exports = router; ``` #### **5. `app.js`(服务端入口,可选)** ```javascript const express = require('express'); const router = require('./routes'); const { reminderQueue } = require('./queue'); const app = express(); app.use(express.json()); // 解析 JSON 请求体 // 注册路由 app.use('/api', router); // 启动服务 const PORT = 3000; app.listen(PORT, () => { console.log(`服务已启动,端口:${PORT}`); // 启动队列消费者(生产环境建议用独立进程) reminderQueue.isActive() || reminderQueue.process(); }); ``` #### **6. `worker.js`(独立队列消费者,生产环境推荐)** ```javascript const { reminderQueue } = require('./queue'); // 启动消费者(处理队列中的任务) console.log('队列消费者启动,等待任务...'); reminderQueue.process(); ``` ### **三、数据库相关文件(示例)** #### **1. `create-table.sql`(建表语句)** ```sql CREATE DATABASE IF NOT EXISTS `test`; USE `test`; CREATE TABLE IF NOT EXISTS `reminder` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `content` VARCHAR(255) NOT NULL, `user_id` INT NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` ### **四、文件结构总览** ``` project-root/ ├─ package.json # 依赖清单 ├─ .env # 环境变量配置(可选) ├─ redis-client.js # Redis 连接配置 ├─ queue.js # 队列定义与任务处理 ├─ db.js # 数据库连接配置 ├─ routes.js # 接口路由(可选) ├─ app.js # 服务端入口(可选) ├─ worker.js # 队列消费者入口 └─ create-table.sql # 数据库建表语句 ``` ### **五、运行步骤** 1. **启动 Redis 服务** ```bash redis-server # 或通过 Docker 启动 ``` 2. **创建数据库表** ```bash mysql -u root -p < create-table.sql # 执行 SQL 脚本 ``` 3. **安装依赖** ```bash npm install ``` 4. **启动服务端(可选)** ```bash npm start # 启动 Express 服务(提供接口) ``` 5. **启动队列消费者** ```bash npm run worker # 单独进程运行,确保任务被消费 ``` ### **关键说明** - **独立消费者进程**:生产环境中,`worker.js` 应作为独立进程运行(如通过 `pm2` 管理),避免与 Web 服务共用进程导致阻塞。 - **任务持久化**:Redis 会自动将队列任务持久化(依赖 `redis.conf` 中的 `save` 配置),确保服务重启后任务不丢失。 - **扩展场景**:若需处理大量任务,可启动多个消费者实例(`worker.js`)实现负载均衡。