Skip to content

Commit

Permalink
解决选课函数中存在的竞争问题
Browse files Browse the repository at this point in the history
加了相应的unique constraint,并且使用原子的update_or_create,避免在数据库中产生两个相同的记录
  • Loading branch information
Deophius committed Jan 20, 2025
1 parent bcc48bb commit b794367
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 12 deletions.
17 changes: 5 additions & 12 deletions app/course_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,16 +608,13 @@ def registration_status_change(course_id: int, user: NaturalPerson,
and course_status != Course.Status.STAGE2):
return wrong("在非选课阶段不能选课!")

need_to_create = False

if action == "select":
if CourseParticipant.objects.filter(course_id=course_id,
person=user).exists():
participant_info = CourseParticipant.objects.get(
course_id=course_id, person=user)
cur_status = participant_info.status
else:
need_to_create = True
cur_status = CourseParticipant.Status.UNSELECT

if course_status == Course.Status.STAGE1:
Expand Down Expand Up @@ -681,15 +678,11 @@ def registration_status_change(course_id: int, user: NaturalPerson,
course.current_participants += 1
course.save()

# 由于不同用户之间的状态不共享,这个更新应该可以不加锁
if need_to_create:
CourseParticipant.objects.create(course_id=course_id,
person=user,
status=to_status)
else:
CourseParticipant.objects.filter(
course_id=course_id,
person=user).update(status=to_status)
CourseParticipant.objects.update_or_create(
course_id = course_id,
person = user,
defaults = {"status": to_status}
)
succeed("选课成功!", context)
except:
return context
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.9 on 2025-01-17 20:52

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("app", "0008_pool_activity_alter_poolitem_exchange_attributes_and_more"),
]

operations = [
migrations.AddConstraint(
model_name="courseparticipant",
constraint=models.UniqueConstraint(
fields=("course", "person"), name="Unique course selection record"
),
),
]
3 changes: 3 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,9 @@ class CourseParticipant(models.Model):
class Meta:
verbose_name = "4.课程报名情况"
verbose_name_plural = verbose_name
constraints = [
models.UniqueConstraint(fields = ['course', 'person'], name='Unique course selection record')
]

course = models.ForeignKey(Course, on_delete=models.CASCADE,
related_name="participant_set")
Expand Down

0 comments on commit b794367

Please sign in to comment.