Redis-1-format()方法

startFormat()逻辑

startFormat:参数校验与初始化 -- 防重复提交控制 -- 清理旧排版结果 -- 设置任务状态 -- 保存初始状态 -- 异步执行排版任务 -- 日志记录与返回

1. FormatService中:startFormat()

java 复制代码
 public void startFormat(StartFormatRequest request) {
        String nodeId = request.getNodeId();
        Integer styleId = request.getStyleId();
        Long userId = SecurityUtils.getCurrentUserId();

        // 1. 参数校验与初始化: 校验排版样式(fromCode会在styleId无效时抛出异常)
        LayoutStyle.fromCode(styleId);
        // 2.防重复提交控制:检查是否正在处理中.
        // 通过 Redis 检查当前用户是否正在处理相同文件的排版任务,避免重复提交.
        String taskKey = FORMAT_TASK_KEY_PREFIX + userId + ":" + styleId + ":" + nodeId;
        String currentStatus = stringRedisTemplate.opsForValue().get(taskKey);//检查是否正在处理中
        if (TASK_PROCESSING.equals(currentStatus)) {
            log.info("FormatService##startFormat-1,文件正在排版处理中,请勿重复提交,nodeId={},styleId={}", nodeId, styleId);
            throw new BizException(ErrorCode.BUSINESS_ERROR, "文件正在排版处理中,请勿重复提交");
        }
        // ....

        // 3. 清理该文件的旧排版结果(同一userId + sourceNodeId 只保留最新一次)
        // 调用 cleanupOldFormatResults 方法删除用户历史排版结果,确保只保留最新一次排版数据。
        cleanupOldFormatResults(userId, nodeId);
        // 4.设置任务状态为处理中(24小时过期)
        // 在 Redis 中设置任务状态为"处理中"(PROCESSING),并设置 24 小时过期时间
        stringRedisTemplate.opsForValue().set(taskKey, TASK_PROCESSING, 24, TimeUnit.HOURS);
        // 5. 保存初始状态:立即保存"排版中"状态的结果项,让前端可以立即查询到
        // 调用 saveFormattingResultItem 方法立即保存"排版中"状态的结果项,供前端实时查询
        saveFormattingResultItem(nodeId, fileName, userId);
        // 6. 异步执行排版任务:通过ApplicationContext获取代理对象,调用doFormatAsync方法异步执行排版逻辑
        // 通过 ApplicationContext 获取代理对象调用,触发 @Async 异步执行
        // 直接调用 doFormatAsync() 不会走 AOP 代理,@Async 不生效
        // 注意:Spring 使用 JDK 动态代理,需要通过接口类型获取 Bean
        FormatService proxy = applicationContext.getBean(FormatService.class);
        proxy.doFormatAsync(styleId, null, nodeId, fileId, fileName, userId, taskKey);
        // 7.日志记录与返回:方法立即返回,前端通过轮询 query 接口查询排版状态
        // 记录关键操作日志,方法执行后立即返回,前端通过轮询接口查询排版状态
        log.info("FormatService##startFormat-6,排版任务已提交异步执行,nodeId={}", nodeId);
    }

(1)设置任务状态 :①目的:防止重复提交任务。②实现方式:通过 Redis 的 stringRedisTemplate.opsForValue().set(taskKey, TASK_PROCESSING, 24, TimeUnit.HOURS) 设置一个键值对;taskKey 是基于用户 ID、样式 ID 和文件节点 ID 生成的唯一标识;值为 TASK_PROCESSING("PROCESSING"),表示当前任务正在进行中;过期时间为 24 小时,确保任务状态不会永久占用 Redis。③作用:在方法开头检查该键是否存在且值为 TASK_PROCESSING,如果存在则抛出异常,提示用户"文件正在排版处理中,请勿重复提交";避免同一用户对同一文件重复发起排版任务。
(2) 保存初始状态 :①目的:记录排版任务的初始信息,供前端实时查询。②实现方式:调用 saveFormattingResultItem 方法,将"排版中"状态的结果项保存到 Redis;该方法会创建一个 FormatResultItem 对象,状态为 FORMATTING,并将其序列化后存储到 Redis 中;同时更新用户与文件的映射关系(通过 FORMAT_USER_KEY_PREFIX 和 FORMAT_SOURCE_KEY_PREFIX)。③作用:提供给前端查询接口使用,前端可以通过轮询获取当前任务的状态(如"排版中");即使异步任务尚未完成,前端也能立即感知到任务已启动。

(3)清理旧版结果:为了清除与当前用户和原文件相关的历史排版任务数据。包括以下几类历史数据:①旧排版结果项详情:清理 Redis 中存储的旧排版结果项(FormatResultItem),这些数据以 format:item:{resultNodeId} 为键,包含排版任务的状态、文件名等信息;②用户与原文件的映射关系:清理 format:source:{userId}:{sourceNodeId} 键对应的 Set 数据,该 Set 存储了原文件的所有排版结果 resultNodeId 列表;③从 format:user:{userId} 键对应的 Set 中移除原文件的 sourceNodeId,表示该用户不再关联此原文件的排版记录。

相关推荐
IvorySQL2 小时前
PG 日报|新增 VACUUM 全维度统计信息补丁迭代
数据库·人工智能·postgresql·ivorysql
白露与泡影4 小时前
Redis 缓存实战:雪崩、穿透、击穿一次讲透
数据库·redis·缓存
Steadfast_GG5 小时前
Redis典型应用 - 缓存,缓存更新策略,内存淘汰策略,缓存预热,缓存穿透,缓存雪崩,缓存击穿
redis·缓存穿透·缓存击穿·缓存雪崩·缓存预热·缓存更新策略·内存淘汰策略
赵渝强老师5 小时前
【赵渝强老师】使用Oracle可传输的表空间迁移数据
数据库·oracle
IpdataCloud6 小时前
跨区服玩家延迟高怎么办?用IP离线库自动分配到最近服务器
数据库·tcp/ip·github·php·ip
wuqingshun3141597 小时前
MYSQL默认的事务隔离级别是什么?为什么选择这个级别?
数据库·mysql
空中湖7 小时前
电池简史(五):极限之梦与终章——锂硫、锂空气、量子电池,以及你该知道的电池投资与生活指南
数据库·程序人生
蓝胖子酱9 小时前
在 Electron 中用 electron-store 实现加密存储与自定义格式文件
前端·javascript·数据库
snow@li9 小时前
Redis:数据库语法速查表 / 全景梳理
数据库·redis·缓存
Devlive 开源社区9 小时前
Nebula 1.6.0 发布:跨区域桶自动路由、秒传、文本/PDF 预览一次到位
数据库·sql