From 03b273d6cd417f21f983cf1da8a17e7f675b9cb0 Mon Sep 17 00:00:00 2001 From: zty Date: Mon, 29 Jul 2024 16:06:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:exam=20=E4=BF=AE=E6=94=B9=E8=80=83=E8=AF=95?= =?UTF-8?q?=E7=9A=84=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/apps/exam/views.py | 92 +++++++++++++++-------------------- server/server/settings_dev.py | 2 +- 2 files changed, 41 insertions(+), 53 deletions(-) diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index 421920e..1bcb8e8 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -688,33 +688,38 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G courese_ids = [i.id for i in course] current_date = now_data.strftime('%Y-%m-%d') cer_number = now_data.strftime('%Y%m%d') - # redis 连接并获取锁 - cache.set("certificate", str(uuid.uuid4()), timeout=60) - # 查询证明编号创建时间为最后一个 - cer = Certificate.objects.latest('证书编号') - if cer: - cer_number = int(cer.证书编号[5:]) + 1 - cer_number = 'CTCZL' + str(cer_number) - data_dict = { - '姓名': request.user.name, - '用户ID': request.user.id, - '证书编号': cer_number, - '证书方案': '202312', - '单位名称': request.user.dept.full_name, - '所属单位': '国检测试控股集团'+request.user.dept.name, - '发证日期': current_date, - '培训日期':current_date, - '培训结束日期': current_date, - '课程列表': courese_ids, - 'examrecord': er.id, - } - serializer = CertificateSerializer(data=data_dict) - serializer.is_valid(raise_exception=True) - serializer.save() - val = cache.get("certificate") - if val: # 如果存在,则删除 - # 释放锁 - cache.delete("certificate") + # 获取锁 + iden = acquire_lock('certificate') + if iden is None: + raise ParseError("系统忙,请稍后再试。", status=503) + try: + # 查询证明编号创建时间为最后一个 + cer = Certificate.objects.latest('证书编号') + if cer: + cer_number = int(cer.证书编号[5:]) + 1 + cer_number = 'CTCZL' + str(cer_number) + data_dict = { + '姓名': request.user.name, + '用户ID': request.user.id, + '证书编号': cer_number, + '证书方案': '202312', + '单位名称': request.user.dept.full_name, + '所属单位': '国检测试控股集团'+request.user.dept.name, + '发证日期': current_date, + '培训日期':current_date, + '培训结束日期': current_date, + '课程列表': courese_ids, + 'examrecord': er.id, + } + serializer = CertificateSerializer(data=data_dict) + serializer.is_valid(raise_exception=True) + serializer.save() + except Exception as e: + import traceback + raise ParseError(traceback.print_exc()) + finally: + release_lock('certificate', iden) + er.took = (now - er.create_time).total_seconds() er.end_time = now er.belong_dept=request.user.dept @@ -723,31 +728,14 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G return Response(ExamRecordListSerializer(instance=er).data) -def acquire_lock(redis_conn, lock_name, ttl): +def acquire_lock(lock_name, timeout=60): identifier = str(uuid.uuid4()) - lock = redis_conn.set(lock_name, identifier, nx=True, ex=ttl) + lock = cache.add(lock_name, identifier, timeout=timeout, nx=True) return identifier if lock else None - -import redis -def release_lock(redis_conn, lock_name, identifier): - with redis_conn.pipeline() as pipe: - try: - while True: - try: - pipe.watch(lock_name) - # 使用 multi/exec 模式来确保原子性 - if pipe.get(lock_name) == identifier: - pipe.multi() - pipe.delete(lock_name) - pipe.execute() - return True - # 如果锁已经被修改,取消监视 - pipe.unwatch() - return False - except redis.exceptions.WatchError: - # 如果在监视期间锁被修改,重试 - continue - except redis.exceptions.RedisError as e: - print(f"Error releasing lock: {e}") - return False \ No newline at end of file +def release_lock(lock_name, identifier): + if cache.get(lock_name) == identifier: + cache.delete(lock_name) + return True + else: + raise ParseError('Lock identifier does not match') \ No newline at end of file diff --git a/server/server/settings_dev.py b/server/server/settings_dev.py index e08b21d..38a0036 100644 --- a/server/server/settings_dev.py +++ b/server/server/settings_dev.py @@ -1,5 +1,5 @@ from .settings import * -DEBUG = True +DEBUG = False DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.postgresql',