#!/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': '内部错误'}