批量查询在线成员对应节点redis

package com.kongjs.im.message.service;


import com.alibaba.fastjson2.JSON;
import com.kongjs.im.common.dto.UserDeviceOnlineDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;


import java.util.*;

@Slf4j
@Service
public class ImOnlineService {

    private static final String USER_ONLINE = "im:online:device:{%s}";

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 【同步非响应式】
     * 批量获取多个用户的 完整在线设备信息(Hash 全量数据)
     *
     * @param userIds 用户ID列表
     * @return Map<userId, Map<deviceId, UserDeviceOnlineDTO>>
     */
    public Map<Long, Map<String, UserDeviceOnlineDTO>> batchGetUserOnlineInfo(List<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return Collections.emptyMap();
        }
        // 1. 构建批量 KEY
        List<String> keys = new ArrayList<>();
        for (Long userId : userIds) {
            keys.add(String.format(USER_ONLINE, userId));
        }
        // 2. Lua 脚本:批量 hgetall
        DefaultRedisScript<List<List<String>>> script = new DefaultRedisScript<>();
        script.setScriptText("""
                    local result = {}
                    for i = 1, #KEYS do
                        local data = redis.call('HGETALL', KEYS[i])
                        table.insert(result, data)
                    end
                    return result
                """);
        //script.setResultType(List.class);
        // 3. 执行 Lua(同步)
        List<List<String>> rawResult = stringRedisTemplate.execute(script, keys);
        // 4. 解析结果
        Map<Long, Map<String, UserDeviceOnlineDTO>> finalMap = new HashMap<>(rawResult.size());
        for (int i = 0; i < userIds.size(); i++) {
            Long userId = userIds.get(i);
            List<String> hashData = rawResult.get(i);
            Map<String, UserDeviceOnlineDTO> deviceMap = new HashMap<>();
            for (int j = 0; j < hashData.size(); j += 2) {
                String deviceId = hashData.get(j);
                String json = hashData.get(j + 1);
                // JSON 转你的 DTO
                UserDeviceOnlineDTO dto = null;
                try {
                    dto = JSON.parseObject(json, UserDeviceOnlineDTO.class);
                } catch (Exception e) {
                    log.error("{}", e.getMessage());
                }
                if (dto != null) {
                    deviceMap.put(deviceId, dto);
                }
            }
            finalMap.put(userId, deviceMap);
        }
        return finalMap;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值