/* * * Copyright 2017-2018 [email protected](xiaoyu) * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, see <http://www.gnu.org/licenses/>. * */ package org.dromara.raincat.manager.service.impl; import org.apache.commons.collections.CollectionUtils; import org.dromara.raincat.common.constant.CommonConstant; import org.dromara.raincat.common.enums.TransactionRoleEnum; import org.dromara.raincat.common.enums.TransactionStatusEnum; import org.dromara.raincat.common.holder.DateUtils; import org.dromara.raincat.common.netty.bean.TxTransactionGroup; import org.dromara.raincat.common.netty.bean.TxTransactionItem; import org.dromara.raincat.manager.config.Constant; import org.dromara.raincat.manager.service.TxManagerService; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.text.ParseException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; /** * TxManagerServiceImpl. * @author xiaoyu */ @Component @SuppressWarnings("unchecked") public class TxManagerServiceImpl implements TxManagerService { private final RedisTemplate redisTemplate; @Autowired public TxManagerServiceImpl(final RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Override public Boolean saveTxTransactionGroup(final TxTransactionGroup txTransactionGroup) { try { final String groupId = txTransactionGroup.getId(); //保存数据 到sortSet redisTemplate.opsForZSet().add(CommonConstant.REDIS_KEY_SET, groupId, CommonConstant.REDIS_SCOPE); final List<TxTransactionItem> itemList = txTransactionGroup.getItemList(); if (CollectionUtils.isNotEmpty(itemList)) { for (TxTransactionItem item : itemList) { redisTemplate.opsForHash().put(cacheKey(groupId), item.getTaskKey(), item); } } } catch (Exception e) { return false; } return true; } @Override public Boolean addTxTransaction(final String txGroupId, final TxTransactionItem txTransactionItem) { try { redisTemplate.opsForHash().put(cacheKey(txGroupId), txTransactionItem.getTaskKey(), txTransactionItem); } catch (Exception e) { return false; } return true; } @Override public List<TxTransactionItem> listByTxGroupId(final String txGroupId) { final Map<Object, TxTransactionItem> entries = redisTemplate.opsForHash().entries(cacheKey(txGroupId)); final Collection<TxTransactionItem> values = entries.values(); return new ArrayList<>(values); } @Override public void removeRedisByTxGroupId(final String txGroupId) { redisTemplate.delete(cacheKey(txGroupId)); } @Override public void updateTxTransactionItemStatus(final String key, final String hashKey, final int status, final Object message) { try { final TxTransactionItem item = (TxTransactionItem) redisTemplate.opsForHash().get(cacheKey(key), hashKey); item.setStatus(status); if (Objects.nonNull(message)) { item.setMessage(message); } //计算耗时 final String createDate = item.getCreateDate(); final LocalDateTime now = LocalDateTime.now(); try { final LocalDateTime createDateTime = DateUtils.parseLocalDateTime(createDate); final long consumeTime = DateUtils.getSecondsBetween(createDateTime, now); item.setConsumeTime(consumeTime); } catch (ParseException e) { e.printStackTrace(); } redisTemplate.opsForHash().put(cacheKey(key), item.getTaskKey(), item); } catch (BeansException e) { e.printStackTrace(); } } @Override public int findTxTransactionGroupStatus(final String txGroupId) { try { final TxTransactionItem item = (TxTransactionItem) redisTemplate.opsForHash().get(cacheKey(txGroupId), txGroupId); return item.getStatus(); } catch (BeansException e) { e.printStackTrace(); return TransactionStatusEnum.ROLLBACK.getCode(); } } @Override public void removeCommitTxGroup() { final Set<String> keys = redisTemplate.keys(Constant.REDIS_KEYS); keys.parallelStream().forEach(key -> { final Map<Object, TxTransactionItem> entries = redisTemplate.opsForHash().entries(key); final Collection<TxTransactionItem> values = entries.values(); final boolean present = values.stream() .anyMatch(item -> item.getStatus() != TransactionStatusEnum.COMMIT.getCode()); if (!present) { redisTemplate.delete(key); } }); } @Override public void removeRollBackTxGroup() { final Set<String> keys = redisTemplate.keys(Constant.REDIS_KEYS); keys.parallelStream().forEach(key -> { final Map<Object, TxTransactionItem> entries = redisTemplate.opsForHash().entries(key); final Collection<TxTransactionItem> values = entries.values(); final Optional<TxTransactionItem> any = values.stream().filter(item -> item.getRole() == TransactionRoleEnum.START.getCode() && item.getStatus() == TransactionStatusEnum.ROLLBACK.getCode()) .findAny(); if (any.isPresent()) { redisTemplate.delete(key); } }); } private String cacheKey(final String key) { return String.format(CommonConstant.REDIS_PRE_FIX, key); } }