refactor: 获取授权树或者资产列表时避免读时锁

pull/5690/head
xinwen 2021-03-03 15:36:42 +08:00 committed by Jiangjie.Bai
parent 91a26abf9e
commit 78bf6f5817
2 changed files with 33 additions and 25 deletions

View File

@ -29,8 +29,12 @@ class AllGrantedAssetPagination(GrantedAssetPaginationBase):
def get_count_from_nodes(self, queryset): def get_count_from_nodes(self, queryset):
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
return None return None
assets_amount = sum(UserAssetGrantedTreeNodeRelation.objects.filter( values = UserAssetGrantedTreeNodeRelation.objects.filter(
user=self._user, node_parent_key='' user=self._user, node_parent_key=''
).values_list('node_assets_amount', flat=True)) ).values_list('node_assets_amount', flat=True)
if not values:
return None
assets_amount = sum(values)
logger.debug(f'Hit all assets amount {assets_amount} -> {self._request.get_full_path()}') logger.debug(f'Hit all assets amount {assets_amount} -> {self._request.get_full_path()}')
return assets_amount return assets_amount

View File

@ -1,5 +1,6 @@
from collections import defaultdict from collections import defaultdict
from typing import List, Tuple from typing import List, Tuple
import time
from django.core.cache import cache from django.core.cache import cache
from django.conf import settings from django.conf import settings
@ -185,11 +186,16 @@ class UserGrantedTreeRefreshController:
return {org_id.decode() for org_id in org_ids} return {org_id.decode() for org_id in org_ids}
def set_all_orgs_as_builed(self): def set_all_orgs_as_builed(self):
orgs_id = [str(org_id) for org_id in self.orgs_id] self.client.sadd(self.key, *self.orgs_id)
self.client.sadd(self.key, *orgs_id)
def have_need_refresh_orgs(self):
builded_org_ids = self.client.smembers(self.key)
builded_org_ids = {org_id.decode() for org_id in builded_org_ids}
have = self.orgs_id - builded_org_ids
return have
def get_need_refresh_orgs_and_fill_up(self): def get_need_refresh_orgs_and_fill_up(self):
orgs_id = set(str(org_id) for org_id in self.orgs_id) orgs_id = self.orgs_id
with self.client.pipeline() as p: with self.client.pipeline() as p:
p.smembers(self.key) p.smembers(self.key)
@ -197,8 +203,7 @@ class UserGrantedTreeRefreshController:
ret = p.execute() ret = p.execute()
builded_orgs_id = {org_id.decode() for org_id in ret[0]} builded_orgs_id = {org_id.decode() for org_id in ret[0]}
ids = orgs_id - builded_orgs_id ids = orgs_id - builded_orgs_id
orgs = set() orgs = {*Organization.objects.filter(id__in=ids)}
orgs.update(Organization.objects.filter(id__in=ids))
logger.info(f'Need rebuild orgs are {orgs}, builed orgs are {ret[0]}, all orgs are {orgs_id}') logger.info(f'Need rebuild orgs are {orgs}, builed orgs are {ret[0]}, all orgs are {orgs_id}')
return orgs return orgs
@ -285,7 +290,7 @@ class UserGrantedTreeRefreshController:
@lazyproperty @lazyproperty
def orgs_id(self): def orgs_id(self):
ret = {org.id for org in self.orgs} ret = {str(org.id) for org in self.orgs}
return ret return ret
@lazyproperty @lazyproperty
@ -297,12 +302,12 @@ class UserGrantedTreeRefreshController:
def refresh_if_need(self, force=False): def refresh_if_need(self, force=False):
user = self.user user = self.user
with UserGrantedTreeRebuildLock(user_id=user.id):
with tmp_to_root_org(): with tmp_to_root_org():
UserAssetGrantedTreeNodeRelation.objects.filter(user=user).exclude(org_id__in=self.orgs_id).delete() UserAssetGrantedTreeNodeRelation.objects.filter(user=user).exclude(org_id__in=self.orgs_id).delete()
exists = UserAssetGrantedTreeNodeRelation.objects.filter(user=user).exists()
if force or not exists: if force or self.have_need_refresh_orgs():
with UserGrantedTreeRebuildLock(user_id=user.id):
if force:
orgs = self.orgs orgs = self.orgs
self.set_all_orgs_as_builed() self.set_all_orgs_as_builed()
else: else:
@ -310,8 +315,11 @@ class UserGrantedTreeRefreshController:
for org in orgs: for org in orgs:
with tmp_to_org(org): with tmp_to_org(org):
t_start = time.time()
logger.info(f'Rebuild user tree: user={self.user} org={current_org}')
utils = UserGrantedTreeBuildUtils(user) utils = UserGrantedTreeBuildUtils(user)
utils.rebuild_user_granted_tree() utils.rebuild_user_granted_tree()
logger.info(f'Rebuild user tree ok: cost={time.time() - t_start} user={self.user} org={current_org}')
class UserGrantedUtilsBase: class UserGrantedUtilsBase:
@ -353,15 +361,11 @@ class UserGrantedTreeBuildUtils(UserGrantedUtilsBase):
asset_ids = list(asset_ids) asset_ids = list(asset_ids)
return asset_ids return asset_ids
@timeit
@ensure_in_real_or_default_org @ensure_in_real_or_default_org
def rebuild_user_granted_tree(self): def rebuild_user_granted_tree(self):
""" """
注意调用该方法一定要被 `UserGrantedTreeRebuildLock` 锁住 注意调用该方法一定要被 `UserGrantedTreeRebuildLock` 锁住
""" """
logger.info(f'Rebuild user tree: user={self.user} org={current_org}')
user = self.user user = self.user
# 先删除旧的授权树🌲 # 先删除旧的授权树🌲