From 4583beaec0b362156471a658ef3b68246d0ba36a Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 26 Mar 2020 13:11:38 +0800 Subject: [PATCH] =?UTF-8?q?[Update]=20=E5=88=9B=E5=BB=BAAuthBook=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=9A=84=E6=96=B9=E6=B3=95=E4=BB=8EModelManager?= =?UTF-8?q?=E4=B8=AD=E7=A7=BB=E5=8A=A8=E5=88=B0Model=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E5=8E=9F=E7=94=9F=E7=9A=84=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?create=E6=96=B9=E6=B3=95=EF=BC=9B=E5=90=8C=E6=97=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=8B=E5=8A=A1=E5=A4=84=E7=90=86=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/backends/manager.py | 2 +- apps/assets/models/authbook.py | 52 ++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/apps/assets/backends/manager.py b/apps/assets/backends/manager.py index 5d1966688..ee6650ed5 100644 --- a/apps/assets/backends/manager.py +++ b/apps/assets/backends/manager.py @@ -155,7 +155,7 @@ class AssetUserManager: @staticmethod def create(**kwargs): # 使用create方法创建AuthBook对象,解决并发创建问题(添加锁机制) - authbook = AuthBook.objects.create(**kwargs) + authbook = AuthBook.create(**kwargs) return authbook def __getattr__(self, item): diff --git a/apps/assets/models/authbook.py b/apps/assets/models/authbook.py index 2c96f9bdb..2c8c0c051 100644 --- a/apps/assets/models/authbook.py +++ b/apps/assets/models/authbook.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -from django.db import models +from django.db import models, transaction from django.db.models import Max from django.core.cache import cache from django.utils.translation import ugettext_lazy as _ @@ -18,25 +18,7 @@ class AuthBookQuerySet(models.QuerySet): class AuthBookManager(OrgManager): - - def get_max_version(self, username, asset): - version_max = self.filter(username=username, asset=asset)\ - .aggregate(Max('version')) - version_max = version_max['version__max'] or 0 - return version_max - - def create(self, **kwargs): - username = kwargs['username'] - asset = kwargs['asset'] - key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id) - with cache.lock(key_lock, expire=60): - self.filter(username=username, asset=asset, is_latest=True)\ - .update(is_latest=False) - max_version = self.get_max_version(username, asset) - kwargs['version'] = max_version + 1 - kwargs['is_latest'] = True - obj = super().create(**kwargs) - return obj + pass class AuthBook(BaseUser): @@ -59,6 +41,36 @@ class AuthBook(BaseUser): def generate_id_with_asset(self, asset): return self.id + @classmethod + def get_max_version(cls, username, asset): + version_max = cls.objects.filter(username=username, asset=asset) \ + .aggregate(Max('version')) + version_max = version_max['version__max'] or 0 + return version_max + + @classmethod + def create(cls, **kwargs): + """ + 使用并发锁机制创建AuthBook对象, (主要针对并发创建 username, asset 相同的对象时) + 并更新其他对象的 is_latest=False (其他对象: 与当前对象的 username, asset 相同) + 同时设置自己的 is_latest=True, version=max_version + 1 + """ + username = kwargs['username'] + asset = kwargs['asset'] + key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id) + with cache.lock(key_lock): + with transaction.atomic(): + cls.objects.filter( + username=username, asset=asset, is_latest=True + ).update(is_latest=False) + max_version = cls.get_max_version(username, asset) + kwargs.update({ + 'version': max_version + 1, + 'is_latest': True + }) + obj = cls.objects.create(**kwargs) + return obj + @property def connectivity(self): return self.get_asset_connectivity(self.asset)