有没有办法避免在这种情况下创建重复的用户?

时间:2019-08-20 05:46:34

标签: python flask flask-sqlalchemy

我正在创建Flask应用程序以分析公司中的某些行为。而且Intranet网站向我发送了一个Webhook,以告诉我何时有人登录某个地方。

问题在于,有时Intranet会向我发送两次相同的Webhook,而我的装饰器first_or_create_user似乎同时被触发,因此如果不存在,它将创建两倍的用户。

因此,我收到了一些有关Webhooks的信息:

{
  'id': 9349813, 
  'begin_at': '2019-08-20 05:34:53 UTC', 
  'end_at': None, 
  'host': '<ip>', 
  'user': {
    'id': 62812, 
    'login': '<login>'
  }
}

我的路线是这样写的:

@intrahook.route('', methods=["POST"])
@check_params
@first_or_create_user
def index(user):
    return _hook_handler(request.headers.get("X-Model"), request.headers.get("X-Event"), request.json)

和我的装饰器:

def first_or_create_user(f):
    wraps(f)
    def get_user(*args, **kwargs):
        data = request.json
        user = User.query.filter_by(
            intra_id=data['user']['id']
        ).first()

        if user is None:
            intra_user = ic.get(f"users/{data['user']['id']}").json()

            user = User(
                    intra_id=data['user']['id'],
                    login=data['user']['login'],
                    first_name=intra_user['first_name'],
                    last_name=intra_user['last_name'],
                    pool_year=intra_user['pool_year'],
                    pool_month=intra_user['pool_month']
                )

            db.session.add(user)
            db.session.commit()

            logger.info(f"user_creation: {data['user']['login']}")

        return f(user, *args, **kwargs)
    return get_user

我想知道是否有任何方法可以锁定/避免同时触发first_or_create_user。

我知道内部网不应在同一时间发送相同的呼叫,但我不是内部网网站的维护者,可惜的是,我无法对其进行改进。

谢谢。

1 个答案:

答案 0 :(得分:0)

所以最后我确实将unique = True添加到intra_id列并登录。

最后找到了如何“修复”此问题。

实际上,内部api需要太多时间来回答我:

intra_user = ic.get(f"users/{data['user']['id']}").json()

所以我只是添加了另一项检查,然后再保存到数据库中。

这是最终代码:

def first_or_create_user(f):
    wraps(f)
    def get_user(*args, **kwargs):
        data = request.json
        user = User.query.filter_by(
            intra_id=data['user']['id']
        ).first()

        if user is None:
            intra_user = ic.get(f"users/{data['user']['id']}").json()

            user = User(
                    intra_id=data['user']['id'],
                    login=data['user']['login'],
                    first_name=intra_user['first_name'],
                    last_name=intra_user['last_name'],
                    pool_year=intra_user['pool_year'],
                    pool_month=intra_user['pool_month']
                )

            u = User.query.filter_by(intra_id=data['user']['id']).first()
            if u is None:
                db.session.add(user)
                db.session.commit()
                logger.info(f"user_creation: {data['user']['login']}")
            else:
                return f(u, *args, **kwargs)
        return f(user, *args, **kwargs)
    return get_user

谢谢您的帮助。