MallServiceImpl.java 7.99 KB
package vion.service.impl.monitor;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.codec.MqttQoS;
import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vion.dto.monitor.MallDTO;
import vion.mapper.monitor.MallMapper;
import vion.model.monitor.*;
import vion.service.monitor.IEventRecordService;
import vion.service.monitor.IMAccountService;
import vion.service.monitor.IMallService;
import vion.service.monitor.IRAgentEventService;
import vion.utils.JsonUtil;
import vion.utils.TopicUtil;
import vion.vo.monitor.MallVO;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author vion
 * @date 2024/10/31
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MallServiceImpl extends MPJBaseServiceImpl<MallMapper, Mall> implements IMallService {

    private final IMAccountService accountService;
    private final IEventRecordService eventRecordService;
    private final IRAgentEventService agentEventService;
    private final MqttClientTemplate client;
    private final Converter converter;

    @Override
    public Page<MAccount> listAccount(MAccount dto) {
        return accountService.lambdaQuery(dto).page(Page.of(dto.getPageNum(), dto.getPageSize()));
    }

    @Override
    public Page<MallVO> list(MallDTO dto) {
        Assert.notNull(dto.getAgentType(), "agentType 不能为空");
        var wrapper = new MPJLambdaWrapper<>(converter.convert(dto, Mall.class))
                .selectAll(Mall.class)
                .selectAs(MAccount::getName, MallVO::getAccountName)
                .leftJoin(MAccount.class, MAccount::getUid, Mall::getAccountUid)
                .orderByDesc(Mall::getUpdateTime);
        return this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), MallVO.class, wrapper);
    }

    @Override
    public MallVO get(Long id) {
        var wrapper = new MPJLambdaWrapper<Mall>()
                .selectAll(Mall.class)
                .selectAs(MAccount::getName, MallVO::getAccountName)
                .leftJoin(MAccount.class, MAccount::getUid, Mall::getAccountUid)
                .eq(Mall::getId, id);
        return this.selectJoinOne(MallVO.class, wrapper);
    }

    @Override
    public Page<MallVO> listAttention(MallDTO dto) {
        Assert.notNull(dto.getAgentType(), "agentType 不能为空");
        var wrapper = new MPJLambdaWrapper<>(converter.convert(dto, Mall.class))
                .selectAll(Mall.class)
                .selectAs(MAccount::getName, MallVO::getAccountName)
                .selectAs(Agent::getHostname, MallVO::getHostname)
                .leftJoin(MAccount.class, MAccount::getUid, Mall::getAccountUid)
                .leftJoin(Agent.class, Agent::getUid, Mall::getAgentUid)
                .eq(Mall::getAttention, 1)
                .orderByDesc(Mall::getUid, Mall::getUpdateTime);
        var mallVOPage = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), MallVO.class, wrapper);
        Opt.ofEmptyAble(mallVOPage.getRecords())
                .ifPresent(r -> {
                    var mallUidList = r.stream().map(MallVO::getUid).toList();
                    // fixme {@link EventServiceImpl #51}
                    var eventRecWrapper = Wrappers.<EventRecord>query()
                            .select("DISTINCT on (mall_uid) *")
                            .in("mall_uid", mallUidList)
                            .orderByDesc("mall_uid", "create_time");
                    var eventRecordList = eventRecordService.list(eventRecWrapper);
                    var mallUid2RecMap = eventRecordList.stream().collect(Collectors.groupingBy(EventRecord::getMallUid));

                    var agentEventList = agentEventService.lambdaQuery().in(RAgentEvent::getMallUid, mallUidList).list();
                    var mallUid2AgentEventMap = agentEventList.stream().collect(Collectors.groupingBy(RAgentEvent::getMallUid));

                    r.forEach(tmp -> {
                        tmp.setEventRecordList(mallUid2RecMap.getOrDefault(tmp.getUid(), List.of()));
                        tmp.setAgentEventList(mallUid2AgentEventMap.getOrDefault(tmp.getUid(), List.of()));
                    });
                });
        return mallVOPage;
    }

    @Override
    public Page<MallVO> listErrorAttention(MallDTO dto) {
        var eventRecWrapper = Wrappers.<EventRecord>query()
                .select("DISTINCT on (mall_uid) *")
                .eq("agent_type", dto.getAgentType())
                .ne("status", 1)
                .orderByDesc("mall_uid", "create_time");
        var eventRecordList = eventRecordService.list(eventRecWrapper);
        if (CollUtil.isEmpty(eventRecordList)) {
            return null;
        }
        var mallUidList = eventRecordList.stream().map(EventRecord::getMallUid).toList();
        var agentEventList = agentEventService.lambdaQuery().in(RAgentEvent::getMallUid, mallUidList).list();
        var mallUid2AgentEventMap = agentEventList.stream().collect(Collectors.groupingBy(RAgentEvent::getMallUid));

        var wrapper = new MPJLambdaWrapper<>(converter.convert(dto, Mall.class))
                .selectAll(Mall.class)
                .selectAs(MAccount::getName, MallVO::getAccountName)
                .selectAs(Agent::getHostname, MallVO::getHostname)
                .leftJoin(MAccount.class, MAccount::getUid, Mall::getAccountUid)
                .leftJoin(Agent.class, Agent::getUid, Mall::getAgentUid)
                .in(Mall::getUid, mallUidList)
                .orderByDesc(Mall::getUid, Mall::getUpdateTime);
        var mallVOPage = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), MallVO.class, wrapper);
        Opt.ofEmptyAble(mallVOPage.getRecords())
                .ifPresent(r -> {
                    var mallUid2SelfMap = eventRecordList.stream().collect(Collectors.groupingBy(EventRecord::getMallUid));
                    r.forEach(tmp -> {
                        tmp.setEventRecordList(mallUid2SelfMap.getOrDefault(tmp.getUid(), List.of()));
                        tmp.setAgentEventList(mallUid2AgentEventMap.getOrDefault(tmp.getUid(), List.of()));
                    });
                });
        return mallVOPage;
    }

    @Override
    public String attention(List<MallDTO> dtoList) {
        this.updateBatchById(converter.convert(dtoList, Mall.class));
        return "关注成功";
    }

    @Override
    public String attentionByAccount(String accountUid) {
        var mallList = this.lambdaQuery().eq(Mall::getAccountUid, accountUid).list();
        mallList.forEach(mall -> mall.setAttention((short) 1));
        this.updateBatchById(mallList);
        return "批量关注成功";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String cancelAttention(Long id) {
        var attentionMall = this.getById(id);
        this.lambdaUpdate().set(Mall::getAttention, 0).eq(Mall::getId, id).update(new Mall());
        var agentEventList = agentEventService.lambdaQuery().eq(RAgentEvent::getMallUid, attentionMall.getUid()).list();
        var topic = TopicUtil.getEventTopic(attentionMall.getAgentUid());
        if (StrUtil.isBlank(topic)) {
            var msg = StrUtil.format("agent:{} 获取topic失败", attentionMall.getAgentUid());
            log.error(msg);
            return msg;
        }
        agentEventList.forEach(agentEvent -> client.publish(topic, JsonUtil.toJsonByte(agentEvent), MqttQoS.QOS2));
        agentEventService.lambdaUpdate().eq(RAgentEvent::getMallUid, attentionMall.getUid()).remove();
        return "取消成功";
    }
}