feat: base 优化safe_get_or_create

This commit is contained in:
caoqianming 2025-12-03 13:52:08 +08:00
parent 9388eada7d
commit 53a56ace1f
1 changed files with 16 additions and 18 deletions

View File

@ -117,25 +117,23 @@ class BaseModel(models.Model):
def safe_get_or_create(cls, defaults=None, **kwargs): def safe_get_or_create(cls, defaults=None, **kwargs):
defaults = defaults or {} defaults = defaults or {}
for attempt in range(3): for i in range(3):
try:
obj = cls.objects.create(**kwargs, **defaults)
return obj, True
except IntegrityError:
try: try:
# 先尝试获取(带锁) # 有别的进程抢先创建了,直接 get
try: obj = cls.objects.get(**kwargs)
obj = cls.objects.select_for_update().get(**kwargs) return obj, False
return obj, False except cls.DoesNotExist:
except cls.DoesNotExist: # 极端并发情况下 create 和 get 都失败,稍微等一下重试
# 不存在则创建 time.sleep(0.001 * (i + 1)) # 微等一下避免竞争
obj = cls(**kwargs, **defaults) continue
obj.save()
return obj, True # 最终重试失败(极罕见)
except IntegrityError: obj = cls.objects.get(**kwargs)
# 发生唯一约束冲突时重试 return obj, False
if attempt == 2:
raise
time.sleep(0.1 * (attempt + 1))
except Exception:
# 其他异常直接抛出
raise
def handle_parent(self): def handle_parent(self):