feat: base 优化safe_get_or_create以处理并发

This commit is contained in:
caoqianming 2024-12-30 10:24:12 +08:00
parent c5d8f70251
commit 28c72e01b9
1 changed files with 14 additions and 8 deletions

View File

@ -112,15 +112,21 @@ class BaseModel(models.Model):
abstract = True abstract = True
@classmethod @classmethod
def safe_get_or_create(cls, **kwargs): def safe_get_or_create(cls, defaults=None, **kwargs):
defaults = kwargs.pop('defaults', {}) defaults = defaults or {}
for attempt in range(5):
with transaction.atomic():
try: try:
return cls.objects.get_or_create(defaults=defaults, **kwargs) ins = cls.objects.select_for_update().get(**kwargs)
return ins, False
except cls.DoesNotExist:
try:
ins = cls.objects.create(**defaults, **kwargs)
except IntegrityError: except IntegrityError:
if attempt < 4: try:
time.sleep(0.1) return cls.objects.get(**kwargs), False
else: except cls.DoesNotExist:
pass
raise raise
def handle_parent(self): def handle_parent(self):