外层若在事务里,IntegrityError 会中止整个事务,导致回查抛 TransactionManagementError。当前未开 ATOMIC_REQUESTS 所以还没触发, 但仓库多处用了 transaction.atomic(),属于随时会踩的坑。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
56 lines
1.8 KiB
Python
56 lines
1.8 KiB
Python
from django.core.cache import cache
|
||
from django.db import IntegrityError, transaction
|
||
|
||
from utils.constants import CacheKey
|
||
|
||
from .models import ProblemTag
|
||
|
||
|
||
def clear_tag_cache():
|
||
"""标签列表接口按 keyword 分键缓存,标签一变就整批清掉"""
|
||
cache.delete_pattern(f"{CacheKey.problem_tags}:*")
|
||
|
||
|
||
def find_tags(names):
|
||
"""按名字大小写不敏感查已有标签,查不到就跳过,不创建"""
|
||
tags = []
|
||
seen = set()
|
||
for raw in names:
|
||
name = (raw or "").strip()
|
||
if not name or name.lower() in seen:
|
||
continue
|
||
seen.add(name.lower())
|
||
tag = ProblemTag.objects.filter(name__iexact=name).first()
|
||
if tag is not None:
|
||
tags.append(tag)
|
||
return tags
|
||
|
||
|
||
def resolve_tags(names):
|
||
"""把前端传来的标签名解析成 ProblemTag:去空格、大小写不敏感复用已有标签,没有才新建"""
|
||
tags = []
|
||
seen = set()
|
||
created = False
|
||
for raw in names:
|
||
name = (raw or "").strip()
|
||
if not name or name.lower() in seen:
|
||
continue
|
||
seen.add(name.lower())
|
||
tag = ProblemTag.objects.filter(name__iexact=name).first()
|
||
if tag is None:
|
||
try:
|
||
# 包一层 atomic:外层若在事务里,IntegrityError 会中止整个事务,
|
||
# 导致下面的回查抛 TransactionManagementError
|
||
with transaction.atomic():
|
||
tag = ProblemTag.objects.create(name=name)
|
||
created = True
|
||
except IntegrityError:
|
||
# 并发下另一个请求刚建好同名标签,回查复用
|
||
tag = ProblemTag.objects.filter(name__iexact=name).first()
|
||
if tag is None:
|
||
continue
|
||
tags.append(tag)
|
||
if created:
|
||
clear_tag_cache()
|
||
return tags
|