项目实训 增加消息确认机制及通信断开转存至mysql

在上次设计好实现思路与搭好整体实现框架后,目前实现了websocket+redis存储的核心逻辑。

首先声明建立存储房间:

    private static StringRedisTemplate redisTemplateUserRoom;


    @Resource
    public void setRedisTemplateUserRoom(StringRedisTemplate redisTemplateUserRoom){WebSocketServer.redisTemplateUserRoom = redisTemplateUserRoom;}

由于websocket是双工通讯,需要建立发送确认机制,避免丢包;发送方为用户与AI进行对话,因此需要指定AI的Id:

private String AI = "123";

private boolean isAckSay = true;

private boolean isAckCorr = true;

private long startTimeSay;

private long startTimeCorr;

 当用户向客户端发送消息后,会调用OnMessage函数,后端向大模型发送请求,获得对话,并将其存在redis房间中,加入消息确认功能逻辑:

    @OnMessage
    public void onMessage(String message, Session session){
        //TODO: 用户向Websocket客户端发送消息,会调用该函数
        //TODO: ack#say#{AI消息序号},用户向Websocket客户端发送消息,会调用该函数
        String[] request;
        request = message.split("#");

        //后续存储在MySQL里的时候,只需要判断dialog的sender是否为AI就可以吧

        if(request[0].equals("ack")){
            if(request[1].equals("say")){
                //TODO:格式ack#say#{AI消息序号} 发过去的回应被收到了
                isAckSay = true;//接收到了ack才能继续

            }else if(request[1].equals("corr")){

                isAckCorr = true;

            }else{
                throw new RuntimeException();
            }



        }else if(request[0].equals("say")&&isAckSay&&isAckCorr){
            //格式say#{用户消息序号}#{用户回应},用户传来文本,需要调用大模型

            //TODO:先把用户的文本存一个dialog
            redisStor(userId,userId,request[2]);
            //收到用户的say后向用户回确认
            String messageToUser = "ack#say#{用户消息序号}";
            sendMessageTo(userId,messageToUser);

            //TODO:存储大模型纠错作为一个dialog
            //纠错我就理解为对一个dialog纠错了
            String content = modelTestCorr(request[2]);
            redisStor(userId,AI,content);
            messageToUser = "corr#{用户消息序号}#"+content;
            isAckCorr = false;
            sendMessageTo(userId,messageToUser);
            startTimeCorr = System.currentTimeMillis();
            while(!isAckCorr&&((System.currentTimeMillis()-startTimeCorr)/1000)>5){
                //当没收到ack并且已经过了5秒了,超时重传
                sendMessageTo(userId,messageToUser);
                startTimeCorr = System.currentTimeMillis();
            }

            //TODO:存储大模型说的话返回结果为一个dialog
            //这里实际上要把redis中的数据拿出来给大模型,是否为直接转成字符串?
            //需要什么格式,下面仅是个测试
            content = modelTestSay("AI回复");
            redisStor(userId,AI,content);

            //向用户发送AI回复
            messageToUser = "say#{AI消息序号}#"+content;
            sendMessageTo(userId,messageToUser);
            isAckSay = false;
            startTimeSay = System.currentTimeMillis();
            while(!isAckSay&&((System.currentTimeMillis()-startTimeSay)/1000)>5){
                //当没收到ack并且已经过了5秒了
                sendMessageTo(userId,messageToUser);
                startTimeSay = System.currentTimeMillis();
            }
        }
        if(!StringUtil.isNullOrEmpty(message)){
            logger.info("收到id为" + userId + "的用户发来消息:" + message);

        }
    }

Redis存储逻辑:

 private void redisStor(String userId,String senderId,String content){
        Date currentTimeUser = new Date();
        Dialog dialogUser = new Dialog();
        User sender = new User();
        Optional <User> uop = userRepository.findUserById(Long.parseLong(senderId));
        if(uop.isEmpty()){
            sendMessage("用户不存在"); //这不能不存在吧,token都找到了,需要异常处理吗?
        }else{
            sender = uop.get();
        }
        boolean keyExists = redisTemplateUserRoom.hasKey(userId);

        dialogUser.setSender(sender);
        dialogUser.setContent(content);
        dialogUser.setTime(currentTimeUser);
        //没有userId这个键值,会自己创建一个空的吧
        RedisUtils.add(userId,dialogUser,redisTemplateUserRoom);
        }

连接断开后,将redis里的内容转存mysql数据库逻辑:

 //断开连接后,会把数据存到数据库
        List<Dialog> dialogs = RedisUtils.getList(userId,redisTemplateUserRoom,Dialog.class);
        //将dialog存入数据库

        dialogRepository.saveAll(dialogs);

        TrainingData trainingData = new TrainingData();
        trainingData.setUser(userRepository.findUserById(Long.parseLong(userId)).get());
        trainingData.setDialogs(dialogs);


        //调用接口,获取score
        //将trainingData存入数据库
        trainingDataRepository.save(trainingData);


        redisTemplateUserRoom.delete(userId);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值