背景:
目标是把 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());
}
}
最初的逻辑: