基于Cloud Functions实现每日课程定时检测与重复触发方案咨询
基于Firebase Cloud Functions实现课程提醒方案
一、添加课程时启动5分钟延迟检查
当用户在Firestore中新增课程文档时,通过Firestore触发器创建Cloud Task,设置延迟执行时间为「课程开始时间+5分钟」,到点后自动触发课程完成状态检查,并向未标记完成的教师发送邮件提醒。
实现步骤
- 提前在Google Cloud控制台启用Cloud Tasks API,创建专属队列(例如
course-check-queue),队列区域需与Cloud Functions部署区域保持一致。 - 编写Firestore onCreate触发器函数,调度延迟任务:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const { CloudTasksClient } = require("@google-cloud/tasks"); admin.initializeApp(); const client = new CloudTasksClient(); exports.scheduleCourseCheck = functions.firestore.document('courses/{courseId}') .onCreate(async (snap, context) => { const courseData = snap.data(); const courseStartTime = new Date(courseData.startTime); // 假设startTime为ISO格式字符串/时间戳 const checkTime = new Date(courseStartTime.getTime() + 5 * 60 * 1000); // 课程开始后5分钟执行检查 // 构建Cloud Task请求参数 const project = process.env.GCP_PROJECT; const location = "us-central1"; // 替换为你的函数部署区域 const queue = "course-check-queue"; // 提前创建的队列名称 const handlerUrl = `https://${location}-${project}.cloudfunctions.net/checkCourseCompletion`; const taskPayload = { httpRequest: { httpMethod: "POST", url: handlerUrl, body: Buffer.from(JSON.stringify({ courseId: context.params.courseId })).toString("base64"), headers: { "Content-Type": "application/json" }, }, scheduleTime: { seconds: Math.floor(checkTime.getTime() / 1000) }, }; const queuePath = client.queuePath(project, location, queue); await client.createTask({ parent: queuePath, task: taskPayload }); functions.logger.info(`已调度课程${context.params.courseId}的检查任务,执行时间:${checkTime}`); });
- 编写检查逻辑与邮件发送的HTTP函数:
exports.checkCourseCompletion = functions.https.onRequest(async (req, res) => { try { const { courseId } = req.body; const courseDoc = await admin.firestore().collection('courses').doc(courseId).get(); if (!courseDoc.exists) { functions.logger.error(`课程${courseId}不存在`); return res.status(404).send("课程不存在"); } const courseData = courseDoc.data(); if (!courseData.isCompleted) { // 调用邮件发送逻辑 await sendReminderEmail(courseData.teacherEmail, courseData.courseName); functions.logger.info(`已向教师${courseData.teacherEmail}发送课程${courseId}的完成提醒`); } res.status(200).send("检查完成"); } catch (err) { functions.logger.error("检查任务执行失败:", err); res.status(500).send("执行失败"); } }); // 邮件发送示例(根据实际邮件服务实现) async function sendReminderEmail(teacherEmail, courseName) { // 示例:使用Nodemailer或Firebase Email Extension // 替换为你的实际邮件发送代码 // const transporter = nodemailer.createTransport({ /* 配置邮件服务 */ }); // await transporter.sendMail({ // to: teacherEmail, // subject: `未完成课程提醒:${courseName}`, // text: `您的课程《${courseName}》已结束5分钟,但尚未标记完成,请及时处理。` // }); }
二、每日同一时间重复触发逻辑
针对每日重复的课程,通过Cloud Functions定时Cron任务,每天固定时间(例如凌晨1点)扫描所有有效重复课程,自动生成当日的检查任务。
实现代码
exports.scheduleDailyCourseChecks = functions.pubsub.schedule('0 1 * * *') // 每天凌晨1点执行 .timeZone('Asia/Shanghai') // 替换为你的时区 .onRun(async (context) => { const today = new Date(); // 查询所有每日重复且未过期的课程 const repeatCourses = await admin.firestore().collection('courses') .where('repeatType', '==', 'daily') // 假设repeatType标记为daily表示每日重复 .where('endDate', '>=', today) // 课程未结束 .get(); const taskPromises = []; const project = process.env.GCP_PROJECT; const location = "us-central1"; const queue = "course-check-queue"; const handlerUrl = `https://${location}-${project}.cloudfunctions.net/checkCourseCompletion`; repeatCourses.forEach(doc => { const courseData = doc.data(); // 计算当日课程开始时间 const todayStartTime = new Date(today); todayStartTime.setHours(courseData.startHour, courseData.startMinute, 0, 0); // 假设存储了开始小时/分钟 const checkTime = new Date(todayStartTime.getTime() + 5 * 60 * 1000); // 创建当日的检查任务 const taskPayload = { httpRequest: { httpMethod: "POST", url: handlerUrl, body: Buffer.from(JSON.stringify({ courseId: doc.id })).toString("base64"), headers: { "Content-Type": "application/json" }, }, scheduleTime: { seconds: Math.floor(checkTime.getTime() / 1000) }, }; const queuePath = client.queuePath(project, location, queue); taskPromises.push(client.createTask({ parent: queuePath, task: taskPayload })); }); await Promise.all(taskPromises); functions.logger.info(`已调度${taskPromises.length}个每日重复课程的检查任务`); return null; });
注意事项
- 依赖安装:执行
npm install @google-cloud/tasks firebase-admin firebase-functions安装所需依赖包 - 权限配置:确保Cloud Functions服务账号拥有Cloud Tasks的任务创建权限
- 幂等性处理:检查逻辑中需避免重复发送邮件(例如新增
reminderSent标记字段) - 错误重试:Cloud Tasks默认会重试失败任务,可在队列配置中调整重试策略
内容的提问来源于stack exchange,提问作者AhmedSalem016
相关产品推荐
相关产品推荐

