记录gitlab事件逻辑修改

背景:

目的是把gitlab发送的请求合并。

https://segmentfault.com/a/11...
上次说写合并事件的时候。使用了线程睡眠,不仅会占用tcp连接的时间,也会容易出很多问题。

同时发现了一些问题,后来就改变了写法。

原来的写法:
image.png

流程:

image.png

合并issue close 和 comment事件的时候,后来又发现一个问题:

判断是否同一个issue的方法有错误

之前是通过判断iid是否相等, 请求是否来自同一个请求

image.png

之后发现,issue的iid都是从1 开始的,所以A项目issue 的 iid, 可能与B项目issue 的 iid相同

image.png

所以我们需要区分各个请求来自的项目

所以使用了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: 事件不能合并

image.png

两个可以合并的事件请求一和请求二,如果刚好卡在定时任务发送时间的前后,会导致不能合并。

这个时候就需要在请求接受的时候判断时间, 如果接受的时候小于两秒就不处理。

  /**
     * 是否继续处理
     * 当最后一次请求在当前时间 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());
        }
    }

最后的逻辑:

image.png

583 声望
100 粉丝
0 条评论
推荐阅读
浅谈前端的状态管理,以及anguar的状态管理库
在前端技术中, 状态管理可以帮助你管理“全局”状态 - 那些应用程序的许多部分都需要的状态。比如组件之间共享的数据、页面需要及时更新的数据等等。

weiweiyi阅读 242

记录java 在遍历中删除元素 以及 mysql5.6版本添加unique失败
遍历中删除List或Queue等数据结构中,如何一边遍历一遍删除?1. 常犯错误ArrayList可能没遇到坑过的人会用增强for循环这么写: {代码...} 但是一运行,结果却抛 java.util.ConcurrentModificationException 异常即...

weiweiyi6阅读 939

使用springboot+angular实现web端微信扫码登陆
现在微信的使用用户越来越多,如果网站添加上微信登录,就能节省很多用户注册时间,极大缩小了注册流程。会让用户觉得特别方便。接下来我们就说一下怎么来实现Web端微信扫码登录。

郝泽龙_HZ6阅读 902

利用Docker部署管理LDAP及其初次使用
前言:本周主要写了gitlabWebhook转github的项目,总体上没有遇到什么大问题,这周接触到了LDAP,于是就花时间实际操作了解了一下。

李明5阅读 1.2k

记录本周问题
项目里两个地方都用到了hashmap。但是感觉自己用的时候并没有感觉非常的清晰。同时发现hashmap有线程不安全问题,而自己用的时候就是多线程来使用。于是在这里介绍一下。

weiweiyi5阅读 811

Spring Aop 动态代理
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施...

KerryWu5阅读 8.2k评论 1

Spring Security + JWT
Spring Security默认是基于session进行用户认证的,用户通过登录请求完成认证之后,认证信息在服务器端保存在session中,之后的请求发送上来后SecurityContextPersistenceFilter过滤器从session中获取认证信息、...

4阅读 1.6k

583 声望
100 粉丝
宣传栏