TodoRpcService.java 7.21 KB
package cn.fw.valhalla.rpc.erp;

import cn.fw.data.base.domain.common.Message;
import cn.fw.erp.sdk.api.BacklogItemApi;
import cn.fw.erp.sdk.api.param.BacklogItemCancelReq;
import cn.fw.erp.sdk.api.param.BacklogItemCommitReq;
import cn.fw.erp.sdk.api.param.BacklogItemPlanReq;
import cn.fw.valhalla.rpc.erp.dto.BackLogItemDTO;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : kurisu
 * @className : TodoRpcService
 * @description : erp待办rpc
 * @date: 2020-08-18 15:53
 */
@Slf4j
@Service
public class TodoRpcService {
    private final BacklogItemApi backlogItemApi;
    private final StringRedisTemplate redisTemplate;

    @Value("${follow.todo.failed-prefix}")
    @Getter
    private String keyPrefix;

    @Value("${follow.todo.failed-prefix}:failed")
    @Getter
    private String failedKeyPrefix;

    private final int maxCount = 5;

    @Autowired
    public TodoRpcService(final BacklogItemApi backlogItemApi,
                          final StringRedisTemplate redisTemplate) {
        this.backlogItemApi = backlogItemApi;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 生成待办
     *
     * @param dto
     */
    public boolean push(BackLogItemDTO dto) {
        final String func = "调用ERP系统生成待办";
        final String key = generateKey(TodoOperationEnum.CREATE);
        try {
            log.info("{}:params: [{}]", func, dto);
            if (dto.getCount() > maxCount) {
                setToCache(generateFailKey(TodoOperationEnum.CREATE), dto);
                return true;
            }
            BacklogItemPlanReq req = new BacklogItemPlanReq();
            BeanUtils.copyProperties(dto, req);
            req.setPlanTime(dto.getDataTime());
            Message<Void> message = backlogItemApi.planBacklogItem(req);
            log.info("{} 结果:{} desc: {}", func, message.isSuccess(), message.getResult());
            if (!message.isSuccess()) {
                setToCache(key, dto);
            }
            return message.isSuccess();
        } catch (Exception e) {
            log.error("{}失败,params:{}", func, dto, e);
            setToCache(key, dto);
            return false;
        }
    }

    /**
     * 完成待办
     *
     * @param dto
     */
    public boolean complete(BackLogItemDTO dto) {
        final String func = "调用ERP系统完成待办";
        final String key = generateKey(TodoOperationEnum.COMPLETE);
        try {
            log.info("{}:params: [{}]", func, dto);
            if (dto.getCount() > maxCount) {
                setToCache(generateFailKey(TodoOperationEnum.COMPLETE), dto);
                return true;
            }
            BacklogItemCommitReq req = new BacklogItemCommitReq();
            BeanUtils.copyProperties(dto, req);
            req.setCommitTime(dto.getDataTime());
            Message<Void> message = backlogItemApi.commitBacklogItem(req);
            log.info("{} 结果:{} desc: {}", func, message.isSuccess(), message.getResult());
            if (!message.isSuccess()) {
                setToCache(key, dto);
            }
            return message.isSuccess();
        } catch (Exception e) {
            log.error("{}失败,params:{}", func, dto, e);
            setToCache(key, dto);
            return false;
        }
    }

    /**
     * 取消待办
     *
     * @param dto
     */
    public boolean cancel(BackLogItemDTO dto) {
        final String func = "调用ERP系统取消待办";
        final String key = generateKey(TodoOperationEnum.CANCEL);
        try {
            log.info("{}:params: [{}]", func, dto);
            if (dto.getCount() > maxCount) {
                setToCache(generateFailKey(TodoOperationEnum.CANCEL), dto);
                return true;
            }
            BacklogItemCancelReq req = new BacklogItemCancelReq();
            BeanUtils.copyProperties(dto, req);
            Message<Void> message = backlogItemApi.cancelBacklogItem(req);
            log.info("{} 结果:{} desc: {}", func, message.isSuccess(), message.getResult());
            if (!message.isSuccess()) {
                setToCache(key, dto);
            }
            return message.isSuccess();
        } catch (Exception e) {
            log.error("{}失败,params:{}", func, dto, e);
            setToCache(key, dto);
            return false;
        }
    }

    public String generateKey(final TodoOperationEnum type) {
        return String.format("%s:%s", getKeyPrefix(), type.name());
    }

    public String generateFailKey(final TodoOperationEnum type) {
        return String.format("%s:%s", getFailedKeyPrefix(), type.name());
    }

    public Optional<BackLogItemDTO> getOneFromCache(final String key) {
        try {
            Boolean hasKey = redisTemplate.hasKey(key);
            if (!Boolean.TRUE.equals(hasKey)) {
                return Optional.empty();
            }
            BoundListOperations<String, String> ops = redisTemplate.boundListOps(key);
            String jsonString = ops.leftPop();
            BackLogItemDTO dto = JSONObject.parseObject(jsonString, BackLogItemDTO.class);
            if (Objects.isNull(dto)) {
                return Optional.empty();
            }
            return Optional.of(dto);
        } catch (Exception e) {
            log.error("缓存信息获取失败 key[{}]", key, e);
            return Optional.empty();
        }
    }

    public Collection<BackLogItemDTO> getAllFromCache(final String key) {
        try {
            Boolean hasKey = redisTemplate.hasKey(key);
            if (!Boolean.TRUE.equals(hasKey)) {
                return new HashSet<>();
            }
            BoundListOperations<String, String> ops = redisTemplate.boundListOps(key);
            List<String> stringList = ops.range(0, -1);
            redisTemplate.delete(key);
            if (CollectionUtils.isEmpty(stringList)) {
                return new HashSet<>();
            }
            return stringList.stream().map(str -> JSONObject.parseObject(str, BackLogItemDTO.class)).collect(Collectors.toSet());
        } catch (Exception e) {
            log.error("缓存信息获取失败 key[{}]", key, e);
            return new HashSet<>();
        }
    }

    private void setToCache(final String key, final BackLogItemDTO dto) {
        try {
            dto.setCount(dto.getCount() + 1);
            BoundListOperations<String, String> ops = redisTemplate.boundListOps(key);
            String jsonString = JSONObject.toJSONString(dto);
            ops.rightPush(jsonString);
        } catch (Exception e) {
            log.error("缓存设置信息失败 key[{}]", key, e);
        }
    }

    public enum TodoOperationEnum {
        /**
         * 创建
         */
        CREATE,
        /**
         * 完成
         */
        COMPLETE,
        /**
         * 取消
         */
        CANCEL
    }
}