feat: base 优化safe_get_or_create

This commit is contained in:
caoqianming 2025-09-08 09:28:04 +08:00
parent f97f51e72c
commit 10d4a64c3a
1 changed files with 21 additions and 5 deletions

View File

@ -116,11 +116,27 @@ class BaseModel(models.Model):
@classmethod @classmethod
def safe_get_or_create(cls, defaults=None, **kwargs): def safe_get_or_create(cls, defaults=None, **kwargs):
defaults = defaults or {} defaults = defaults or {}
lock_data = {**kwargs, **defaults}
lock_hash = hashlib.md5(str(lock_data).encode()).hexdigest() for attempt in range(3):
lock_key = f"safe_get_or_create:{cls.__name__}:{lock_hash}" try:
with cache.lock(lock_key, timeout=10): with transaction.atomic():
return cls.objects.get_or_create(**kwargs, defaults=defaults) # 先尝试获取(带锁)
try:
obj = cls.objects.select_for_update().get(**kwargs)
return obj, False
except cls.DoesNotExist:
# 不存在则创建
obj = cls(**kwargs, **defaults)
obj.save()
return obj, True
except IntegrityError:
# 发生唯一约束冲突时重试
if attempt == 2:
raise
time.sleep(0.1 * (attempt + 1))
except Exception:
# 其他异常直接抛出
raise
def handle_parent(self): def handle_parent(self):