背景:
目标是把gitlab发送的申请合并。
https://segmentfault.com/a/11...
上次说写合并事件的时候。应用了线程睡眠,不仅会占用tcp连贯的工夫,也会容易出很多问题。
同时发现了一些问题,起初就扭转了写法。
原来的写法:
流程:
合并issue close 和 comment事件的时候,起初又发现一个问题:
判断是否同一个issue的办法有谬误
之前是通过判断iid是否相等, 申请是否来自同一个申请
之后发现,issue的iid都是从1 开始的,所以A我的项目issue 的 iid, 可能与B我的项目issue 的 iid雷同
所以咱们须要辨别各个申请来自的我的项目
所以应用了ConcurrentHashMap,key为token,value为该我的项目待处理的GitlabRequest申请
/** * key: access_token, github钉钉机器人的token * value 该我的项目待处理的GitlabRequest申请 */ private final Map<String, Queue<GitlabRequest>> map = new ConcurrentHashMap<>();
问题2: 线程睡眠
上次。应用了线程睡眠,不仅会占用tcp连贯的工夫,也会容易出很多问题。
改为了应用@Schedule
// 距离5s解决我的项目申请 @Scheduled(fixedRate = 5000) private void sendRequest() { // 对每个我的项目的申请队列进行解决 this.map.forEach((key, value) -> { try { this.handleQueue(value); } catch (IOException e) { throw new RuntimeException(e); } }); }
问题3: 事件不能合并
两个能够合并的事件申请一和申请二,如果刚好卡在定时工作发送工夫的前后,会导致不能合并。
这个时候就须要在申请承受的时候判断工夫, 如果承受的时候小于两秒就不解决。
/** * 是否持续解决 * 当最初一次申请在以后工夫 2s 内时, 不进行解决 * * @return true 不解决 false 解决 */ private Boolean IsNotHandle(Timestamp receivedTime) { return System.currentTimeMillis() < receivedTime.getTime() + NOT_HANDLE_TIME; }
解决申请队列:
public void handleQueue(Queue<GitlabRequest> queue) throws IOException { int size = queue.size(); // 如果队列没数据,示意这段时间没有申请,间接返回 if (size == 0) { return; } Iterator<GitlabRequest> iterator = queue.iterator(); while (iterator.hasNext()) { // 获取头部元素 GitlabRequest gitlabRequest = iterator.next(); // 是否持续进行解决 if (IsNotHandle(gitlabRequest.getReceivedTime())) { logger.info("最初一次申请在以后工夫在2s内,不进行解决"); break; } // 出栈 iterator.remove(); String resultJson; // 获取解决合并事件后的json resultJson = this.combineEventService.handleEvent(iterator, gitlabRequest); if (resultJson == null) { logger.info("事件合并,不发送该事件"); return; } this.gitLabNotifyService.handleEventData(resultJson, gitlabRequest.getEventName(), gitlabRequest.getSecret()); } }
最初的逻辑: