You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
flyapps/fir_ser/common/utils/pending.py

82 lines
3.4 KiB

3 years ago
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月
# author: NinEveN
# date: 2022/3/15
import logging
import time
from django.core.cache import cache
from common.cache.storage import PendingStateCache
logger = logging.getLogger(__name__)
def set_pending_cache(unique_key, cache_data, cache_obj, timeout):
if unique_key in cache_data:
cache_data.remove(unique_key)
logger.warning(f'return unique_key:{unique_key} cache_data: {cache_data} ')
cache_obj.set_storage_cache(cache_data, timeout)
def get_pending_result(func, expect_func, loop_count=10, sleep_time=3, unique_key='default_key',
run_func_count=2, pop_first=True, *args, **kwargs):
"""
:param func: 将要运行的函数对象
:param expect_func: 期待的运行结果函数
:param loop_count: 执行次数
:param sleep_time: 执行循环等待时间
:param unique_key: 11请求唯一标识用与函数并发请求
:param run_func_count: 11函数并发请求数超过该次数会自动移除多余等待
:param pop_first: 11超出是否自动移除最老的请求True: 移除最老的 False: 移除最新的
:param args:
:param kwargs:
:return:
"""
locker_key = kwargs.pop('locker_key')
cache_timeout = loop_count * sleep_time * (run_func_count + 1)
cache_obj = PendingStateCache(locker_key)
cache_data = cache_obj.get_storage_cache()
is_pop = False
if cache_data and isinstance(cache_data, list):
if unique_key not in cache_data:
cache_data.append(unique_key)
if len(cache_data) > run_func_count and len(cache_data) > 0:
is_pop = True
if pop_first:
cache_data.pop(0)
else:
cache_data.pop()
else:
cache_data = [unique_key]
cache_obj.set_storage_cache(cache_data, cache_timeout)
if not pop_first and len(cache_data) == run_func_count and is_pop:
logger.warning(f'unique_key:{unique_key} cache_data: {cache_data} ')
return True, {'err_msg': '请求重复,请稍后再试'}
try:
with cache.lock(f"get_pending_result_{locker_key}", timeout=loop_count * sleep_time):
count = 1
while True:
cache_data = cache_obj.get_storage_cache()
logger.warning(f'unique_key:{unique_key} cache_data: {cache_data} ')
if cache_data and isinstance(cache_data, list) and unique_key in cache_data:
result = func(*args, **kwargs)
if expect_func(result, *args, **kwargs):
set_pending_cache(unique_key, cache_data, cache_obj, cache_timeout)
return True, {'data': result}
time.sleep(sleep_time)
if loop_count < count:
set_pending_cache(unique_key, cache_data, cache_obj, cache_timeout)
return False, {'err_msg': '请求超时'}
count += 1
else:
set_pending_cache(unique_key, cache_data, cache_obj, cache_timeout)
return True, {'err_msg': '请求重复,请稍后再试'}
except Exception as e:
logger.warning(f'get pending result exception: {e}')
set_pending_cache(unique_key, cache_data, cache_obj, cache_timeout)
return False, {'err_msg': '内部错误'}