cn.webank.queue.biz.service.impl.RetryMessagePojoService.java Source code

Java tutorial

Introduction

Here is the source code for cn.webank.queue.biz.service.impl.RetryMessagePojoService.java

Source

/**
 * Copyright (C) @2014 Webank Group Holding Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.webank.queue.biz.service.impl;

import java.util.List;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import redis.clients.jedis.Jedis;
import cn.webank.framework.biz.service.support.WeBankServiceDispatcher;
import cn.webank.framework.dto.BaseDTO;
import cn.webank.framework.dto.BizError;
import cn.webank.framework.dto.BizErrors;
import cn.webank.framework.mapper.JsonMapper;
import cn.webank.framework.message.SolacePojoService;
import cn.webank.queue.dto.RetryMessageDTO;
import cn.webank.queue.model.RetryMessage;
import cn.webank.queue.pool.SentinelShardedPool;

/**
 * 
 * @author jonyang
 *
 */
@Service("cn.webank.queue.biz.service.RetryMessageService")
public class RetryMessagePojoService {
    private final static Logger LOG = LoggerFactory.getLogger(RetryMessagePojoService.class);

    @Autowired
    @Qualifier("sentinelShardedJedisPool")
    private SentinelShardedPool sentinelShardedPool;

    @Autowired
    @Qualifier("retryTaskExecutor")
    private ThreadPoolTaskExecutor taskExecutor;

    /**
     * ??
     */
    @Autowired
    @Qualifier("cn.webank.framework.biz.service.support.WeBankServiceDispatcher")
    private WeBankServiceDispatcher serviceDispatcher;

    /**
     * ???
     */
    @Autowired
    @Qualifier("messageSource")
    private ReloadableResourceBundleMessageSource bundleMessageSource;

    @Autowired
    @Qualifier("cn.webank.framework.message.SolaceService")
    private SolacePojoService solaceService;

    @Value("${jedis.retry.namespace}")
    private String namespace;

    @Value("${jedis.retry.queue}")
    private String queueName;

    private JsonMapper jsonMapper = JsonMapper.nonDefaultMapper();

    // ?10
    @Scheduled(cron = "0/10 * * * * ?")
    public void scan() {
        List<Jedis> jedises = sentinelShardedPool.getResources();
        for (Jedis jedis : jedises) {
            String msg = getMessage(namespace, queueName, jedis);
            if (msg == null)
                continue;

            RetryMessageDTO retryDto = jsonMapper.fromJson(msg, RetryMessageDTO.class);
            RetryMessage retryMessage = new RetryMessage(retryDto);
            if (retryMessage.isExpired() || retryMessage.isOverThreshHold()) {
                // send to solace error queue
            } else if (retryMessage.isEnableExecute()) {
                executeMessage(namespace, queueName, taskExecutor, jsonMapper, serviceDispatcher, solaceService,
                        bundleMessageSource, retryDto, this);
            } else {
                saveMessage(namespace, queueName, retryDto.getKey(), jsonMapper.toJson(retryDto));
            }

        }

    }

    private void executeMessage(String namespace, String queueName, ThreadPoolTaskExecutor taskExecutor,
            JsonMapper jsonMapper, WeBankServiceDispatcher serviceDispatcher, SolacePojoService solaceService,
            ReloadableResourceBundleMessageSource bundleMessageSource, RetryMessageDTO retryDto,
            RetryMessagePojoService retryService) {
        StringBuilder bizSeqNos = new StringBuilder();
        try {

            String msg = retryDto.getJsonMessage();
            final BaseDTO baseDto = jsonMapper.fromJson(msg, BaseDTO.class);

            bizSeqNos.append(baseDto.getBizSeqNo() + "\n");

            Runnable r = constructRunnable(namespace, queueName, baseDto, retryDto, serviceDispatcher,
                    solaceService, bundleMessageSource, retryService, jsonMapper);

            // dispatch service
            taskExecutor.submit(r);

        } catch (Exception e) {
            LOG.error("system error,bizSeqNos:" + bizSeqNos.toString(), e);
        }
    }

    private static Runnable constructRunnable(final String namespace, final String queueName, final BaseDTO baseDTO,
            final RetryMessageDTO retryDto, final WeBankServiceDispatcher serviceDispatcher,
            // final int timeoutSeconds,
            final SolacePojoService solaceService, final ReloadableResourceBundleMessageSource bundleMessageSource,
            final RetryMessagePojoService retryService, final JsonMapper jsonMapper) {

        Runnable r = new Runnable() {
            public void run() {
                // 4.1 dispatch service

                try {
                    //retry?
                    long currentTime = System.currentTimeMillis();
                    retryDto.addRetryTimes();
                    retryDto.setLastExecutedTime(currentTime);

                    BizErrors errors = new BizErrors();

                    // TODO ?2
                    serviceDispatcher.dispatch(baseDTO.getServiceId(), retryDto.getJsonMessage(), errors);

                    // handle result
                    if (errors.hasErrors()) {
                        StringBuilder sb = new StringBuilder();
                        boolean isFirst = true;
                        for (BizError error : errors.getAllErrors()) {

                            if (!isFirst) {
                                sb.append("<br />");
                            }
                            sb.append(bundleMessageSource.getMessage(error.getCode(), error.getArguments(),
                                    "", Locale.CHINESE));
                            isFirst = false;

                        }

                        LOG.error("biz error:" + sb.toString() + ",message:" + retryDto.getJsonMessage());

                        handleBizException(retryDto);
                    } else {
                        LOG.info("retry message success. key:" + retryDto.getKey() + " ");
                    }

                } catch (Exception e) {
                    // ?
                    LOG.error("distach service error,message:" + retryDto.getJsonMessage(), e);
                    handleSysException(namespace, queueName, retryDto, e, retryService, jsonMapper);

                }

            }
        };

        return r;

    }

    private static void handleSysException(String namespace, String queueName, RetryMessageDTO retryDto,
            Exception e, RetryMessagePojoService retryService, JsonMapper jsonMapper) {

        retryService.saveMessage(namespace, queueName, retryDto.getKey(), jsonMapper.toJson(retryDto));
    }

    private static void handleBizException(RetryMessageDTO retryDto) {
        // send to solace error queue;
        // // 4.2 publish result message
        // try {
        // Assert.notNull(baseDTO,
        // "service response object must not be null");
        // String ecifNo = resultDTO.getEcifNo();
        // String queueName = resultDTO.getQueueName();
        // String topic = resultDTO.getTopic();
        //
        // if (StringUtils.hasText(ecifNo)) {
        // solaceService.doAsyncPublishWithEcifNo(ecifNo,
        // queueName, topic, resultDTO, timeoutSeconds,
        // TimeUnit.SECONDS);
        // } else {
        // solaceService.doAsyncPublish(queueName, topic,
        // resultDTO, timeoutSeconds, TimeUnit.SECONDS);
        // }
        // } catch (Exception e) {
        // LOG.error("publish message error,message:" + messageString,
        // e);
        // return;
        // }
    }

    public void saveMessage(String namespace, String queue, String key, String json) {
        Jedis jedis = sentinelShardedPool.getResource(key);
        String fk = formatKey(namespace, queue);
        jedis.lpush(fk, json);
    }

    public String getMessage(String namespace, String queue, Jedis jedis) {
        String fk = formatKey(namespace, queue);
        List<String> l = jedis.brpop(5, fk);
        return l != null ? l.get(0) : null;
    }

    private String formatKey(String namespace, String queue) {
        return namespace + ":" + queue;
    }

}