如何添加队列服务存储日志并在任务完成时向用户发送通知?
实现步骤指南
1. 梳理现有核心流程节点
先定位两个关键代码位置:
- 任务触发入口:用户上传文件/点击按钮调用的接口,即当前返回
{"action": "in progress"}的接口位置 - 任务结束节点:不管是同步还是异步执行的任务,找到任务执行成功、执行失败的最终结束位置
2. 新建任务状态记录表(基于Postgresql)
新手优先用现有Postgresql实现存储,无需额外引入消息队列中间件,降低上手难度,表结构参考:
CREATE TABLE task_process_record ( id BIGSERIAL PRIMARY KEY, task_unique_id VARCHAR(64) NOT NULL UNIQUE COMMENT '任务唯一标识', task_type VARCHAR(32) NOT NULL COMMENT '任务类型:文件上传/按钮触发对应业务', task_status VARCHAR(16) NOT NULL COMMENT '任务状态:IN_PROGRESS/SUCCESS/FAILED', start_time TIMESTAMP NOT NULL COMMENT '任务启动时间', end_time TIMESTAMP COMMENT '任务结束时间', cost_milliseconds BIGINT COMMENT '任务耗时,单位毫秒', trigger_user_id VARCHAR(64) COMMENT '触发任务的用户ID,用于定向通知', extra_info JSONB COMMENT '扩展字段,存储文件ID、请求参数等自定义内容', create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
3. 改造任务触发接口逻辑
修改现有触发接口的代码:
- 任务启动时生成全局唯一taskId,可通过
UUID.randomUUID().toString().replace("-","")生成 - 向
task_process_record插入一条初始化记录,task_status设为IN_PROGRESS,start_time设为当前时间,填充用户ID、任务类型等字段 - 将原返回的
{"action": "in progress"}调整为携带taskId:{"action": "in progress", "taskId": "生成的唯一ID"},返回给前端 - 按原有逻辑触发业务任务执行,注意如果是异步任务,需要把生成的taskId传递到异步执行逻辑中
注意:如果任务是异步执行的,必须将taskId传递到异步任务的上下文里,否则后续更新任务状态时无法匹配到对应记录
4. 改造任务结束逻辑
在任务执行完成(含成功、失败)的位置新增逻辑:
- 根据传入的taskId查询
task_process_record对应的记录 - 更新
task_status为SUCCESS/FAILED,填入end_time为当前时间,计算耗时cost_milliseconds = end_time.getTime() - start_time.getTime()并存入表中 - 新增通知逻辑:新手可先实现简单的前端轮询方案,新增一个查询接口,参数为taskId,返回任务状态、耗时、执行结果等信息;前端拿到IN_PROGRESS状态时每2-3秒轮询一次接口,拿到结束状态时直接弹窗提示用户即可,后续可升级为WebSocket实现实时推送
5. 可选升级:队列实现优化
如果后续任务量级提升,需要更规范的队列实现,可基于Spring生态扩展:
- 单机场景:用Spring Event实现轻量级消息队列,无需额外中间件
- 分布式场景:集成RabbitMQ/RocketMQ,将任务状态变更事件发送到队列中,消费端统一处理耗时统计、用户通知逻辑
内容的提问来源于stack exchange,提问作者Ritwik1711
相关产品推荐
相关产品推荐

