我正在创建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。
我知道内部网不应在同一时间发送相同的呼叫,但我不是内部网网站的维护者,可惜的是,我无法对其进行改进。
谢谢。
答案 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
谢谢您的帮助。