Java tutorial
/** * 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; } }