funboost 23.5__py3-none-any.whl → 23.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of funboost might be problematic. Click here for more details.
- funboost/__init__.py +1 -1
- funboost/assist/celery_helper.py +18 -7
- funboost/consumers/base_consumer.py +80 -56
- funboost/consumers/celery_consumer.py +20 -4
- funboost/consumers/rabbitmq_amqpstorm_consumer.py +1 -1
- funboost/consumers/redis_consumer_ack_able.py +1 -1
- funboost/consumers/redis_consumer_priority.py +30 -1
- funboost/core/show_funboost_flag.py +48 -0
- funboost/funboost_config_deafult.py +1 -1
- funboost/publishers/base_publisher.py +3 -3
- funboost/publishers/celery_publisher.py +0 -22
- funboost/publishers/redis_publisher.py +3 -13
- funboost/publishers/redis_publisher_priority.py +2 -5
- funboost/publishers/redis_publisher_simple.py +2 -6
- funboost/publishers/redis_pubsub_publisher.py +1 -1
- funboost/publishers/redis_queue_flush.py +11 -0
- funboost/utils/redis_manager.py +2 -2
- {funboost-23.5.dist-info → funboost-23.7.dist-info}/METADATA +11 -3
- {funboost-23.5.dist-info → funboost-23.7.dist-info}/RECORD +22 -20
- {funboost-23.5.dist-info → funboost-23.7.dist-info}/LICENSE +0 -0
- {funboost-23.5.dist-info → funboost-23.7.dist-info}/WHEEL +0 -0
- {funboost-23.5.dist-info → funboost-23.7.dist-info}/top_level.txt +0 -0
funboost/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from funboost.utils.dependency_packages_in_pythonpath import add_to_pythonpath # 这是把 dependency_packages_in_pythonpath 添加到 PYTHONPATH了。
|
|
3
3
|
|
|
4
4
|
from funboost.utils import monkey_patches
|
|
5
|
-
from funboost.
|
|
5
|
+
from funboost.core import show_funboost_flag
|
|
6
6
|
|
|
7
7
|
# noinspection PyUnresolvedReferences
|
|
8
8
|
import nb_log
|
funboost/assist/celery_helper.py
CHANGED
|
@@ -15,7 +15,11 @@ celery_app = celery.Celery(main='funboost_celery', broker=funboost_config_deaful
|
|
|
15
15
|
task_routes={}, timezone=funboost_config_deafult.TIMEZONE, enable_utc=False, )
|
|
16
16
|
|
|
17
17
|
celery_app.conf.task_acks_late = True
|
|
18
|
-
celery_app.conf.
|
|
18
|
+
celery_app.conf.update({
|
|
19
|
+
'worker_redirect_stdouts': False,
|
|
20
|
+
'worker_concurrency': 200
|
|
21
|
+
}
|
|
22
|
+
)
|
|
19
23
|
|
|
20
24
|
logger = get_logger('funboost.CeleryHelper')
|
|
21
25
|
|
|
@@ -30,7 +34,7 @@ class CeleryHelper:
|
|
|
30
34
|
def update_celery_app_conf(celery_app_conf: dict):
|
|
31
35
|
"""
|
|
32
36
|
更新celery app的配置,celery app配置大全见 https://docs.celeryq.dev/en/stable/userguide/configuration.html
|
|
33
|
-
:param celery_app_conf:
|
|
37
|
+
:param celery_app_conf: celery app 配置,字典
|
|
34
38
|
:return:
|
|
35
39
|
"""
|
|
36
40
|
celery_app.conf.update(celery_app_conf)
|
|
@@ -42,7 +46,7 @@ class CeleryHelper:
|
|
|
42
46
|
for k, v in celery_app.conf.items():
|
|
43
47
|
conf_dict_json_able[k] = str(v)
|
|
44
48
|
# print(k, ' : ', v)
|
|
45
|
-
print('celery app 的配置是:',json.dumps(conf_dict_json_able,ensure_ascii=False,indent=4))
|
|
49
|
+
print('celery app 的配置是:', json.dumps(conf_dict_json_able, ensure_ascii=False, indent=4))
|
|
46
50
|
|
|
47
51
|
@staticmethod
|
|
48
52
|
def celery_start_beat(beat_schedule: dict):
|
|
@@ -68,7 +72,7 @@ class CeleryHelper:
|
|
|
68
72
|
threading.Thread(target=_f).start()
|
|
69
73
|
|
|
70
74
|
@classmethod
|
|
71
|
-
def realy_start_celery_worker(cls, worker_name=None):
|
|
75
|
+
def realy_start_celery_worker(cls, worker_name=None, loglevel='INFO'):
|
|
72
76
|
if len(cls.to_be_start_work_celery_queue_name_set) == 0:
|
|
73
77
|
raise Exception('celery worker 没有需要运行的queue')
|
|
74
78
|
queue_names_str = ','.join(list(cls.to_be_start_work_celery_queue_name_set))
|
|
@@ -80,9 +84,16 @@ class CeleryHelper:
|
|
|
80
84
|
pool_name = 'gevent'
|
|
81
85
|
if cls.concurrent_mode == ConcurrentModeEnum.EVENTLET:
|
|
82
86
|
pool_name = 'eventlet'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
'''
|
|
88
|
+
并发数量在app配置中已经制定了。自己用 update_celery_app_conf 方法更新就好了。
|
|
89
|
+
celery_app.conf.update({
|
|
90
|
+
'worker_redirect_stdouts': False,
|
|
91
|
+
'worker_concurrency': 200
|
|
92
|
+
}
|
|
93
|
+
'''
|
|
94
|
+
argv = ['worker', f'--pool={pool_name}',
|
|
95
|
+
'-n', f'worker_funboost_{worker_name}@%h', f'--loglevel={loglevel}',
|
|
96
|
+
f'--queues={queue_names_str}', # 并发数量是
|
|
86
97
|
]
|
|
87
98
|
logger.info(f'celery 启动work参数 {argv}')
|
|
88
99
|
celery_app.worker_main(argv)
|
|
@@ -373,6 +373,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
373
373
|
self._consuming_function_cost_time_total_every_unit_time = 0
|
|
374
374
|
self._last_execute_task_time = time.time() # 最近一次执行任务的时间。
|
|
375
375
|
|
|
376
|
+
self._last_show_remaining_execution_time = 0
|
|
377
|
+
self._show_remaining_execution_time_interval = 300
|
|
378
|
+
|
|
376
379
|
self._msg_num_in_broker = 0
|
|
377
380
|
self._last_timestamp_when_has_task_in_queue = 0
|
|
378
381
|
self._last_timestamp_print_msg_num = 0
|
|
@@ -451,13 +454,13 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
451
454
|
|
|
452
455
|
''' 日志跳转代码行不正确,不用这种方式'''
|
|
453
456
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
457
|
+
def _log_error(self, msg, exc_info=None):
|
|
458
|
+
self.logger.error(msg=f'{msg} \n', exc_info=exc_info, extra={'sys_getframe_n': 3})
|
|
459
|
+
self.error_file_logger.error(msg=f'{msg} \n', exc_info=exc_info, extra={'sys_getframe_n': 3})
|
|
460
|
+
|
|
461
|
+
def _log_critical(self, msg, exc_info=None):
|
|
462
|
+
self.logger.critical(msg=f'{msg} \n', exc_info=exc_info, extra={'sys_getframe_n': 3})
|
|
463
|
+
self.error_file_logger.critical(msg=f'{msg} \n', exc_info=exc_info, extra={'sys_getframe_n': 3})
|
|
461
464
|
|
|
462
465
|
@property
|
|
463
466
|
@decorators.synchronized
|
|
@@ -492,8 +495,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
492
495
|
except BaseException as e:
|
|
493
496
|
log_msg = func.__name__ + ' 运行出错\n ' + traceback.format_exc(
|
|
494
497
|
limit=10) if is_display_detail_exception else str(e)
|
|
495
|
-
self.logger.error(msg=f'{log_msg} \n', exc_info=True)
|
|
496
|
-
self.error_file_logger.error(msg=f'{log_msg} \n', exc_info=True)
|
|
498
|
+
# self.logger.error(msg=f'{log_msg} \n', exc_info=True)
|
|
499
|
+
# self.error_file_logger.error(msg=f'{log_msg} \n', exc_info=True)
|
|
500
|
+
self._log_error(msg=log_msg, exc_info=True)
|
|
497
501
|
finally:
|
|
498
502
|
time.sleep(time_sleep)
|
|
499
503
|
|
|
@@ -524,9 +528,10 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
524
528
|
self._distributed_consumer_statistics.run()
|
|
525
529
|
self.logger.warning(f'启动了分布式环境 使用 redis 的键 hearbeat:{self._queue_name} 统计活跃消费者 ,当前消费者唯一标识为 {self.consumer_identification}')
|
|
526
530
|
|
|
527
|
-
self.keep_circulating(
|
|
531
|
+
self.keep_circulating(60, block=False)(self.check_heartbeat_and_message_count)() # 间隔时间最好比self._unit_time_for_count小整数倍,不然日志不准。
|
|
528
532
|
if self._is_support_remote_kill_task:
|
|
529
|
-
kill_remote_task.RemoteTaskKiller(self.queue_name, None).start_cycle_kill_task()
|
|
533
|
+
self.keep_circulating(10, block=False)(kill_remote_task.RemoteTaskKiller(self.queue_name, None).start_cycle_kill_task)()
|
|
534
|
+
self._is_show_message_get_from_broker = True # 方便用户看到从消息队列取出来的消息的task_id,然后使用task_id杀死运行中的消息。
|
|
530
535
|
if self._do_task_filtering:
|
|
531
536
|
self._redis_filter.delete_expire_filter_task_cycle() # 这个默认是RedisFilter类,是个pass不运行。所以用别的消息中间件模式,不需要安装和配置redis。
|
|
532
537
|
if self._schedule_tasks_on_main_thread:
|
|
@@ -739,8 +744,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
739
744
|
if self._is_push_to_dlx_queue_when_retry_max_times:
|
|
740
745
|
log_msg += f' 。发送到死信队列 {self._dlx_queue_name} 中'
|
|
741
746
|
self.publisher_of_dlx_queue.publish(kw['body'])
|
|
742
|
-
self.logger.critical(msg=f'{log_msg} \n', )
|
|
743
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
747
|
+
# self.logger.critical(msg=f'{log_msg} \n', )
|
|
748
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
749
|
+
self._log_critical(msg=log_msg)
|
|
744
750
|
|
|
745
751
|
if self._get_priority_conf(kw, 'is_using_rpc_mode'):
|
|
746
752
|
# print(function_result_status.get_status_dict(without_datetime_obj=
|
|
@@ -760,23 +766,26 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
760
766
|
if time.time() - self._current_time_for_execute_task_times_every_unit_time > self._unit_time_for_count:
|
|
761
767
|
avarage_function_spend_time = round(self._consuming_function_cost_time_total_every_unit_time / self._execute_task_times_every_unit_time, 4)
|
|
762
768
|
msg = f'{self._unit_time_for_count} 秒内执行了 {self._execute_task_times_every_unit_time} 次函数 [ {self.consuming_function.__name__} ] ,' \
|
|
763
|
-
f'函数平均运行耗时 {avarage_function_spend_time}
|
|
764
|
-
|
|
769
|
+
f'函数平均运行耗时 {avarage_function_spend_time} 秒。 '
|
|
770
|
+
self.logger.debug(msg)
|
|
771
|
+
if self._msg_num_in_broker != -1 and time.time() - self._last_show_remaining_execution_time > self._show_remaining_execution_time_interval: # 有的中间件无法统计或没实现统计队列剩余数量的,统一返回的是-1,不显示这句话。
|
|
765
772
|
# msg += f''' ,预计还需要 {time_util.seconds_to_hour_minute_second(self._msg_num_in_broker * avarage_function_spend_time / active_consumer_num)} 时间 才能执行完成 {self._msg_num_in_broker}个剩余的任务'''
|
|
766
773
|
need_time = time_util.seconds_to_hour_minute_second(self._msg_num_in_broker / (self._execute_task_times_every_unit_time / self._unit_time_for_count) /
|
|
767
774
|
self._distributed_consumer_statistics.active_consumer_num)
|
|
768
|
-
msg += f'''
|
|
769
|
-
|
|
770
|
-
|
|
775
|
+
msg += f''' 预计还需要 {need_time} 时间 才能执行完成 队列 {self.queue_name} 中的 {self._msg_num_in_broker} 个剩余任务'''
|
|
776
|
+
self.logger.info(msg)
|
|
777
|
+
self._last_show_remaining_execution_time = time.time()
|
|
771
778
|
self._current_time_for_execute_task_times_every_unit_time = time.time()
|
|
772
779
|
self._consuming_function_cost_time_total_every_unit_time = 0
|
|
773
780
|
self._execute_task_times_every_unit_time = 0
|
|
781
|
+
|
|
774
782
|
if self._user_custom_record_process_info_func:
|
|
775
783
|
self._user_custom_record_process_info_func(current_function_result_status)
|
|
776
784
|
except BaseException as e:
|
|
777
785
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
778
|
-
self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
779
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
786
|
+
# self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
787
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
788
|
+
self._log_critical(msg=log_msg, exc_info=True)
|
|
780
789
|
|
|
781
790
|
# noinspection PyProtectedMember
|
|
782
791
|
def _run_consuming_function_with_confirm_and_retry(self, kw: dict, current_retry_times,
|
|
@@ -795,12 +804,13 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
795
804
|
function_result_status._has_kill_task = True
|
|
796
805
|
self.logger.warning(f'取消运行 {task_id} {function_only_params}')
|
|
797
806
|
return function_result_status
|
|
798
|
-
function_run = kill_remote_task.kill_fun_deco(task_id)(function_run) #
|
|
807
|
+
function_run = kill_remote_task.kill_fun_deco(task_id)(function_run) # 用杀死装饰器包装起来在另一个线程运行函数,以便等待远程杀死。
|
|
799
808
|
function_result_status.result = function_run(**function_only_params)
|
|
800
809
|
if asyncio.iscoroutine(function_result_status.result):
|
|
801
810
|
log_msg = f'''异步的协程消费函数必须使用 async 并发模式并发,请设置消费函数 {self.consuming_function.__name__} 的concurrent_mode 为 ConcurrentModeEnum.ASYNC 或 4'''
|
|
802
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
803
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
811
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
812
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
813
|
+
self._log_critical(msg=log_msg)
|
|
804
814
|
# noinspection PyProtectedMember,PyUnresolvedReferences
|
|
805
815
|
|
|
806
816
|
os._exit(4)
|
|
@@ -813,8 +823,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
813
823
|
except BaseException as e:
|
|
814
824
|
if isinstance(e, (ExceptionForRequeue,)): # mongo经常维护备份时候插入不了或挂了,或者自己主动抛出一个ExceptionForRequeue类型的错误会重新入队,不受指定重试次数逇约束。
|
|
815
825
|
log_msg = f'函数 [{self.consuming_function.__name__}] 中发生错误 {type(e)} {e} 。消息重新放入当前队列 {self._queue_name}'
|
|
816
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
817
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
826
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
827
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
828
|
+
self._log_critical(msg=log_msg)
|
|
818
829
|
time.sleep(0.1) # 防止快速无限出错入队出队,导致cpu和中间件忙
|
|
819
830
|
# 重回队列如果不修改task_id,insert插入函数消费状态结果到mongo会主键重复。要么保存函数消费状态使用replace,要么需要修改taskikd
|
|
820
831
|
# kw_new = copy.deepcopy(kw)
|
|
@@ -825,21 +836,25 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
825
836
|
function_result_status._has_requeue = True
|
|
826
837
|
if isinstance(e, ExceptionForPushToDlxqueue):
|
|
827
838
|
log_msg = f'函数 [{self.consuming_function.__name__}] 中发生错误 {type(e)} {e},消息放入死信队列 {self._dlx_queue_name}'
|
|
828
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
829
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
839
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
840
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
841
|
+
self._log_critical(msg=log_msg)
|
|
830
842
|
self.publisher_of_dlx_queue.publish(kw['body']) # 发布到死信队列,不重回当前队列
|
|
831
843
|
function_result_status._has_to_dlx_queue = True
|
|
832
844
|
if isinstance(e, kill_remote_task.TaskHasKilledError):
|
|
833
845
|
log_msg = f'task_id 为 {task_id} , 函数 [{self.consuming_function.__name__}] 运行入参 {function_only_params} ,已被远程指令杀死 {type(e)} {e}'
|
|
834
|
-
self.logger.critical(msg=f'{log_msg} ')
|
|
835
|
-
self.error_file_logger.critical(msg=f'{log_msg} ')
|
|
846
|
+
# self.logger.critical(msg=f'{log_msg} ')
|
|
847
|
+
# self.error_file_logger.critical(msg=f'{log_msg} ')
|
|
848
|
+
self._log_critical(msg=log_msg)
|
|
836
849
|
function_result_status._has_kill_task = True
|
|
837
850
|
if isinstance(e, (ExceptionForRequeue, ExceptionForPushToDlxqueue, kill_remote_task.TaskHasKilledError)):
|
|
838
851
|
return function_result_status
|
|
839
852
|
log_msg = f'''函数 {self.consuming_function.__name__} 第{current_retry_times + 1}次运行发生错误,
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
self.
|
|
853
|
+
函数运行时间是 {round(time.time() - t_start, 4)} 秒, 入参是 {function_only_params}
|
|
854
|
+
{type(e)} {e} '''
|
|
855
|
+
# self.logger.error(msg=f'{log_msg} \n', exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
856
|
+
# self.error_file_logger.error(msg=f'{log_msg} \n', exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
857
|
+
self._log_error(msg=log_msg, exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
843
858
|
# traceback.print_exc()
|
|
844
859
|
function_result_status.exception = f'{e.__class__.__name__} {str(e)}'
|
|
845
860
|
function_result_status.result = FunctionResultStatus.FUNC_RUN_ERROR
|
|
@@ -876,8 +891,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
876
891
|
if self._is_push_to_dlx_queue_when_retry_max_times:
|
|
877
892
|
log_msg += f' 。发送到死信队列 {self._dlx_queue_name} 中'
|
|
878
893
|
await simple_run_in_executor(self.publisher_of_dlx_queue.publish, kw['body'])
|
|
879
|
-
self.logger.critical(msg=f'{log_msg} \n', )
|
|
880
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
894
|
+
# self.logger.critical(msg=f'{log_msg} \n', )
|
|
895
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
896
|
+
self._log_critical(msg=log_msg)
|
|
881
897
|
|
|
882
898
|
# self._confirm_consume(kw) # 错得超过指定的次数了,就确认消费了。
|
|
883
899
|
if self._get_priority_conf(kw, 'is_using_rpc_mode'):
|
|
@@ -898,24 +914,26 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
898
914
|
if time.time() - self._current_time_for_execute_task_times_every_unit_time > self._unit_time_for_count:
|
|
899
915
|
avarage_function_spend_time = round(self._consuming_function_cost_time_total_every_unit_time / self._execute_task_times_every_unit_time, 4)
|
|
900
916
|
msg = f'{self._unit_time_for_count} 秒内执行了 {self._execute_task_times_every_unit_time} 次函数 [ {self.consuming_function.__name__} ] ,' \
|
|
901
|
-
f'函数平均运行耗时 {avarage_function_spend_time}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
917
|
+
f'函数平均运行耗时 {avarage_function_spend_time} 秒。 '
|
|
918
|
+
self.logger.debug(msg)
|
|
919
|
+
if self._msg_num_in_broker != -1 and time.time() - self._last_show_remaining_execution_time > self._show_remaining_execution_time_interval: # 有的中间件无法统计或没实现统计队列剩余数量的,统一返回的是-1,不显示这句话。
|
|
920
|
+
# msg += f''' ,预计还需要 {time_util.seconds_to_hour_minute_second(self._msg_num_in_broker * avarage_function_spend_time / active_consumer_num)} 时间 才能执行完成 {self._msg_num_in_broker}个剩余的任务'''
|
|
921
|
+
need_time = time_util.seconds_to_hour_minute_second(self._msg_num_in_broker / (self._execute_task_times_every_unit_time / self._unit_time_for_count) /
|
|
922
|
+
self._distributed_consumer_statistics.active_consumer_num)
|
|
923
|
+
msg += f''' 预计还需要 {need_time} 时间 才能执行完成 队列 {self.queue_name} 中的 {self._msg_num_in_broker} 个剩余任务'''
|
|
924
|
+
self.logger.info(msg)
|
|
925
|
+
self._last_show_remaining_execution_time = time.time()
|
|
910
926
|
self._current_time_for_execute_task_times_every_unit_time = time.time()
|
|
911
927
|
self._consuming_function_cost_time_total_every_unit_time = 0
|
|
912
928
|
self._execute_task_times_every_unit_time = 0
|
|
929
|
+
|
|
913
930
|
if self._user_custom_record_process_info_func:
|
|
914
931
|
await self._user_custom_record_process_info_func(current_function_result_status)
|
|
915
932
|
except BaseException as e:
|
|
916
933
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
917
|
-
self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
918
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
934
|
+
# self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
935
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
936
|
+
self._log_critical(msg=log_msg, exc_info=True)
|
|
919
937
|
|
|
920
938
|
# noinspection PyProtectedMember
|
|
921
939
|
async def _async_run_consuming_function_with_confirm_and_retry(self, kw: dict, current_retry_times,
|
|
@@ -930,8 +948,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
930
948
|
corotinue_obj = self.consuming_function(**function_only_params)
|
|
931
949
|
if not asyncio.iscoroutine(corotinue_obj):
|
|
932
950
|
log_msg = f'''当前设置的并发模式为 async 并发模式,但消费函数不是异步协程函数,请不要把消费函数 {self.consuming_function.__name__} 的 concurrent_mode 设置为 4'''
|
|
933
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
934
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
951
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
952
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
953
|
+
self._log_critical(msg=log_msg)
|
|
935
954
|
# noinspection PyProtectedMember,PyUnresolvedReferences
|
|
936
955
|
os._exit(444)
|
|
937
956
|
if self._function_timeout == 0:
|
|
@@ -949,8 +968,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
949
968
|
except BaseException as e:
|
|
950
969
|
if isinstance(e, (ExceptionForRequeue,)): # mongo经常维护备份时候插入不了或挂了,或者自己主动抛出一个ExceptionForRequeue类型的错误会重新入队,不受指定重试次数逇约束。
|
|
951
970
|
log_msg = f'函数 [{self.consuming_function.__name__}] 中发生错误 {type(e)} {e} 。 消息重新放入当前队列 {self._queue_name}'
|
|
952
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
953
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
971
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
972
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
973
|
+
self._log_critical(msg=log_msg)
|
|
954
974
|
# time.sleep(1) # 防止快速无限出错入队出队,导致cpu和中间件忙
|
|
955
975
|
await asyncio.sleep(0.1)
|
|
956
976
|
# return self._requeue(kw)
|
|
@@ -958,16 +978,19 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
958
978
|
function_result_status._has_requeue = True
|
|
959
979
|
if isinstance(e, ExceptionForPushToDlxqueue):
|
|
960
980
|
log_msg = f'函数 [{self.consuming_function.__name__}] 中发生错误 {type(e)} {e},消息放入死信队列 {self._dlx_queue_name}'
|
|
961
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
962
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
981
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
982
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
983
|
+
self._log_critical(msg=log_msg)
|
|
963
984
|
await simple_run_in_executor(self.publisher_of_dlx_queue.publish, kw['body']) # 发布到死信队列,不重回当前队列
|
|
964
985
|
function_result_status._has_to_dlx_queue = True
|
|
965
986
|
if isinstance(e, (ExceptionForRequeue, ExceptionForPushToDlxqueue)):
|
|
966
987
|
return function_result_status
|
|
967
988
|
log_msg = f'''函数 {self.consuming_function.__name__} 第{current_retry_times + 1}次运行发生错误,
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
self.
|
|
989
|
+
函数运行时间是 {round(time.time() - t_start, 4)} 秒, 入参是 {function_only_params}
|
|
990
|
+
原因是 {type(e)} {e} '''
|
|
991
|
+
# self.logger.error(msg=f'{log_msg} \n', exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
992
|
+
# self.error_file_logger.error(msg=f'{log_msg} \n', exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
993
|
+
self._log_error(msg=log_msg, exc_info=self._get_priority_conf(kw, 'is_print_detail_exception'))
|
|
971
994
|
function_result_status.exception = f'{e.__class__.__name__} {str(e)}'
|
|
972
995
|
function_result_status.result = FunctionResultStatus.FUNC_RUN_ERROR
|
|
973
996
|
return function_result_status
|
|
@@ -1004,8 +1027,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
1004
1027
|
misfire_grace_time = self._get_priority_conf(event.function_kwargs["kw"], 'misfire_grace_time')
|
|
1005
1028
|
log_msg = f''' 现在时间是 {time_util.DatetimeConverter().datetime_str} ,比此任务规定的本应该的运行时间 {event.scheduled_run_time} 相比 超过了指定的 {misfire_grace_time} 秒,放弃执行此任务
|
|
1006
1029
|
{event.function_kwargs["kw"]["body"]} '''
|
|
1007
|
-
self.logger.critical(msg=f'{log_msg} \n')
|
|
1008
|
-
self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
1030
|
+
# self.logger.critical(msg=f'{log_msg} \n')
|
|
1031
|
+
# self.error_file_logger.critical(msg=f'{log_msg} \n')
|
|
1032
|
+
self._log_critical(msg=log_msg)
|
|
1009
1033
|
self._confirm_consume(event.function_kwargs["kw"])
|
|
1010
1034
|
|
|
1011
1035
|
'''
|
|
@@ -156,13 +156,29 @@ class CeleryConsumer(AbstractConsumer):
|
|
|
156
156
|
'''
|
|
157
157
|
|
|
158
158
|
def custom_init(self):
|
|
159
|
-
# 这就是核心,@boost
|
|
159
|
+
# 这就是核心,@boost时候会 @ celery app.task装饰器
|
|
160
160
|
@celery_app.task(name=self.queue_name, rate_limit=f'{self._qps}/s', soft_time_limit=self._function_timeout,
|
|
161
161
|
max_retries=self._max_retry_times,
|
|
162
|
-
**self.broker_exclusive_config['celery_task_config']
|
|
163
|
-
|
|
162
|
+
**self.broker_exclusive_config['celery_task_config'],
|
|
163
|
+
bind=True)
|
|
164
|
+
def f(this, *args, **kwargs):
|
|
164
165
|
self.logger.debug(f' 这条消息是 celery 从 {self.queue_name} 队列中取出 ,是由 celery 框架调度 {self.consuming_function.__name__} 函数处理: args: {args} , kwargs: {kwargs}')
|
|
165
|
-
return self.consuming_function(*args, **kwargs)
|
|
166
|
+
# return self.consuming_function(*args, **kwargs) # 如果没有声明 autoretry_for ,那么消费函数出错了就不会自动重试了。
|
|
167
|
+
try:
|
|
168
|
+
return self.consuming_function(*args, **kwargs)
|
|
169
|
+
except BaseException as exc: # 改成自动重试。
|
|
170
|
+
# print(this.request.__dict__,dir(this))
|
|
171
|
+
|
|
172
|
+
if this.request.retries != self._max_retry_times:
|
|
173
|
+
log_msg = f'fun: {self.consuming_function} args: {args} , kwargs: {kwargs} 消息第{this.request.retries}次运行出错, {exc} \n'
|
|
174
|
+
self._log_error(log_msg, exc_info=self._is_print_detail_exception)
|
|
175
|
+
else:
|
|
176
|
+
log_msg = f'fun: {self.consuming_function} args: {args} , kwargs: {kwargs} 消息达到最大重试次数{this.request.retries}次仍然出错, {exc} \n'
|
|
177
|
+
self._log_critical(log_msg, exc_info=self._is_print_detail_exception)
|
|
178
|
+
# 发生异常,尝试重试任务,countdown 是多少秒后重试
|
|
179
|
+
raise this.retry(exc=exc, countdown=5)
|
|
180
|
+
|
|
181
|
+
celery_app.conf.task_routes.update({self.queue_name: {"queue": self.queue_name}}) # 自动配置celery每个函数使用不同的队列名。
|
|
166
182
|
self.celery_task = f
|
|
167
183
|
CeleryHelper.concurrent_mode = self._concurrent_mode
|
|
168
184
|
|
|
@@ -29,7 +29,7 @@ class RabbitmqConsumerAmqpStorm(AbstractConsumer):
|
|
|
29
29
|
rp = RabbitmqPublisherUsingAmqpStorm(self.queue_name,broker_exclusive_config=self.broker_exclusive_config)
|
|
30
30
|
rp.init_broker()
|
|
31
31
|
rp.channel_wrapper_by_ampqstormbaic.qos(self._concurrent_num)
|
|
32
|
-
rp.channel_wrapper_by_ampqstormbaic.consume(callback=callback, queue=self.queue_name, no_ack=False)
|
|
32
|
+
rp.channel_wrapper_by_ampqstormbaic.consume(callback=callback, queue=self.queue_name, no_ack=False,)
|
|
33
33
|
rp.channel.start_consuming(auto_decode=True)
|
|
34
34
|
|
|
35
35
|
def _confirm_consume(self, kw):
|
|
@@ -156,7 +156,7 @@ class RedisConsumerAckAble(ConsumerConfirmMixinWithTheHelpOfRedisByHearbeat, Abs
|
|
|
156
156
|
kw = {'body': task_dict, 'task_str': task_str}
|
|
157
157
|
self._submit_task(kw)
|
|
158
158
|
else:
|
|
159
|
-
time.sleep(0.
|
|
159
|
+
time.sleep(0.2)
|
|
160
160
|
|
|
161
161
|
def _requeue(self, kw):
|
|
162
162
|
self.redis_db_frame.rpush(self._queue_name, json.dumps(kw['body']))
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"""
|
|
11
11
|
import json
|
|
12
12
|
import time
|
|
13
|
+
|
|
14
|
+
import redis3
|
|
15
|
+
|
|
13
16
|
from funboost.consumers.redis_consumer_ack_able import RedisConsumerAckAble
|
|
14
17
|
|
|
15
18
|
|
|
@@ -49,7 +52,7 @@ class RedisPriorityConsumer(RedisConsumerAckAble):
|
|
|
49
52
|
|
|
50
53
|
BROKER_EXCLUSIVE_CONFIG_DEFAULT = {'x-max-priority': None} # x-max-priority 是 rabbitmq的优先级队列配置,必须为整数,强烈建议要小于5。为None就代表队列不支持优先级。
|
|
51
54
|
|
|
52
|
-
def
|
|
55
|
+
def _shedual_task0000(self):
|
|
53
56
|
|
|
54
57
|
while True:
|
|
55
58
|
# task_str_list = script(keys=[queues_str, self._unack_zset_name], args=[time.time()])
|
|
@@ -64,5 +67,31 @@ class RedisPriorityConsumer(RedisConsumerAckAble):
|
|
|
64
67
|
kw = {'body': task_dict, 'task_str': msg}
|
|
65
68
|
self._submit_task(kw)
|
|
66
69
|
|
|
70
|
+
def _shedual_task(self):
|
|
71
|
+
"""https://redis.readthedocs.io/en/latest/advanced_features.html#default-pipelines """
|
|
72
|
+
while True:
|
|
73
|
+
# task_str_list = script(keys=[queues_str, self._unack_zset_name], args=[time.time()])
|
|
74
|
+
while True:
|
|
75
|
+
try:
|
|
76
|
+
with self.redis_db_frame_version3.pipeline() as p:
|
|
77
|
+
p.watch(self._unack_zset_name, *self.publisher_of_same_queue.queue_list, )
|
|
78
|
+
task_tuple = p.blpop(keys=self.publisher_of_same_queue.queue_list, timeout=60) # 监听了多个键名,所以间接实现了优先级,和kombu的redis 支持优先级的设计思路不谋而合。
|
|
79
|
+
# print(task_tuple)
|
|
80
|
+
if task_tuple:
|
|
81
|
+
msg = task_tuple[1]
|
|
82
|
+
p.zadd(self._unack_zset_name, {msg: time.time()})
|
|
83
|
+
# self.logger.debug(task_tuple)
|
|
84
|
+
p.unwatch()
|
|
85
|
+
p.execute()
|
|
86
|
+
break
|
|
87
|
+
except redis3.WatchError:
|
|
88
|
+
continue
|
|
89
|
+
if task_tuple:
|
|
90
|
+
self._print_message_get_from_broker('redis', msg)
|
|
91
|
+
# self.logger.debug(f'从redis的 [{self._queue_name}] 队列中 取出的消息是: {task_str_list} ')
|
|
92
|
+
task_dict = json.loads(msg)
|
|
93
|
+
kw = {'body': task_dict, 'task_str': msg}
|
|
94
|
+
self._submit_task(kw)
|
|
95
|
+
|
|
67
96
|
def _requeue(self, kw):
|
|
68
97
|
self.publisher_of_same_queue.publish(kw['body'])
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import nb_log
|
|
2
|
+
|
|
3
|
+
logger = nb_log.get_logger('funboost.show_funboost_flag')
|
|
4
|
+
|
|
5
|
+
funboost_flag_str = '''
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
FFFFFFFFFFFFFFFFFFFFFF UUUUUUUU UUUUUUUU NNNNNNNN NNNNNNNN BBBBBBBBBBBBBBBBB OOOOOOOOO OOOOOOOOO SSSSSSSSSSSSSSS TTTTTTTTTTTTTTTTTTTTTTT
|
|
9
|
+
F::::::::::::::::::::F U::::::U U::::::U N:::::::N N::::::N B::::::::::::::::B OO:::::::::OO OO:::::::::OO SS:::::::::::::::S T:::::::::::::::::::::T
|
|
10
|
+
F::::::::::::::::::::F U::::::U U::::::U N::::::::N N::::::N B::::::BBBBBB:::::B OO:::::::::::::OO OO:::::::::::::OO S:::::SSSSSS::::::S T:::::::::::::::::::::T
|
|
11
|
+
FF::::::FFFFFFFFF::::F UU:::::U U:::::UU N:::::::::N N::::::N BB:::::B B:::::B O:::::::OOO:::::::O O:::::::OOO:::::::O S:::::S SSSSSSS T:::::TT:::::::TT:::::T
|
|
12
|
+
F:::::F FFFFFF U:::::U U:::::U N::::::::::N N::::::N B::::B B:::::B O::::::O O::::::O O::::::O O::::::O S:::::S TTTTTT T:::::T TTTTTT
|
|
13
|
+
F:::::F U:::::D D:::::U N:::::::::::N N::::::N B::::B B:::::B O:::::O O:::::O O:::::O O:::::O S:::::S T:::::T
|
|
14
|
+
F::::::FFFFFFFFFF U:::::D D:::::U N:::::::N::::N N::::::N B::::BBBBBB:::::B O:::::O O:::::O O:::::O O:::::O S::::SSSS T:::::T
|
|
15
|
+
F:::::::::::::::F U:::::D D:::::U N::::::N N::::N N::::::N B:::::::::::::BB O:::::O O:::::O O:::::O O:::::O SS::::::SSSSS T:::::T
|
|
16
|
+
F:::::::::::::::F U:::::D D:::::U N::::::N N::::N:::::::N B::::BBBBBB:::::B O:::::O O:::::O O:::::O O:::::O SSS::::::::SS T:::::T
|
|
17
|
+
F::::::FFFFFFFFFF U:::::D D:::::U N::::::N N:::::::::::N B::::B B:::::B O:::::O O:::::O O:::::O O:::::O SSSSSS::::S T:::::T
|
|
18
|
+
F:::::F U:::::D D:::::U N::::::N N::::::::::N B::::B B:::::B O:::::O O:::::O O:::::O O:::::O S:::::S T:::::T
|
|
19
|
+
F:::::F U::::::U U::::::U N::::::N N:::::::::N B::::B B:::::B O::::::O O::::::O O::::::O O::::::O S:::::S T:::::T
|
|
20
|
+
FF:::::::FF U:::::::UUU:::::::U N::::::N N::::::::N BB:::::BBBBBB::::::B O:::::::OOO:::::::O O:::::::OOO:::::::O SSSSSSS S:::::S TT:::::::TT
|
|
21
|
+
F::::::::FF UU:::::::::::::UU N::::::N N:::::::N B:::::::::::::::::B OO:::::::::::::OO OO:::::::::::::OO S::::::SSSSSS:::::S T:::::::::T
|
|
22
|
+
F::::::::FF UU:::::::::UU N::::::N N::::::N B::::::::::::::::B OO:::::::::OO OO:::::::::OO S:::::::::::::::SS T:::::::::T
|
|
23
|
+
FFFFFFFFFFF UUUUUUUUU NNNNNNNN NNNNNNN BBBBBBBBBBBBBBBBB OOOOOOOOO OOOOOOOOO SSSSSSSSSSSSSSS TTTTTTTTTTT
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
'''
|
|
27
|
+
|
|
28
|
+
funboost_flag_str2 = r'''
|
|
29
|
+
|
|
30
|
+
___ ___ ___ ___ ___ ___
|
|
31
|
+
/ /\ /__/\ /__/\ _____ / /\ / /\ / /\ ___
|
|
32
|
+
/ /:/_ \ \:\ \ \:\ / /::\ / /::\ / /::\ / /:/_ / /\
|
|
33
|
+
/ /:/ /\ \ \:\ \ \:\ / /:/\:\ / /:/\:\ / /:/\:\ / /:/ /\ / /:/
|
|
34
|
+
/ /:/ /:/ ___ \ \:\ _____\__\:\ / /:/~/::\ / /:/ \:\ / /:/ \:\ / /:/ /::\ / /:/
|
|
35
|
+
/__/:/ /:/ /__/\ \__\:\ /__/::::::::\ /__/:/ /:/\:| /__/:/ \__\:\ /__/:/ \__\:\ /__/:/ /:/\:\ / /::\
|
|
36
|
+
\ \:\/:/ \ \:\ / /:/ \ \:\~~\~~\/ \ \:\/:/~/:/ \ \:\ / /:/ \ \:\ / /:/ \ \:\/:/~/:/ /__/:/\:\
|
|
37
|
+
\ \::/ \ \:\ /:/ \ \:\ ~~~ \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ /:/ \__\/ \:\
|
|
38
|
+
\ \:\ \ \:\/:/ \ \:\ \ \:\/:/ \ \:\/:/ \ \:\/:/ \__\/ /:/ \ \:\
|
|
39
|
+
\ \:\ \ \::/ \ \:\ \ \::/ \ \::/ \ \::/ /__/:/ \__\/
|
|
40
|
+
\__\/ \__\/ \__\/ \__\/ \__\/ \__\/ \__\/
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
'''
|
|
45
|
+
|
|
46
|
+
logger.debug('\033[0m' + funboost_flag_str2 + '\033[0m')
|
|
47
|
+
|
|
48
|
+
logger.info(f'''分布式函数调度框架funboost文档地址: \033[0m https://funboost.readthedocs.io/zh/latest/ \033[0m ''')
|
|
@@ -27,7 +27,7 @@ from funboost.utils.simple_data_class import DataClassBase
|
|
|
27
27
|
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 以下是中间件连接配置 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
MONGO_CONNECT_URL = f'mongodb://127.0.0.1:27017' # 如果有密码连接 'mongodb://myUserAdmin:8mwTdy1klnSYepNo@192.168.199.202:27016/MONGO_CONNECT_URL = 'mongodb://root:123456@192.168.64.151:27017?authSource=admin'
|
|
30
|
+
MONGO_CONNECT_URL = f'mongodb://127.0.0.1:27017' # 如果有密码连接 'mongodb://myUserAdmin:8mwTdy1klnSYepNo@192.168.199.202:27016/' authSource 指定鉴权db,MONGO_CONNECT_URL = 'mongodb://root:123456@192.168.64.151:27017?authSource=admin'
|
|
31
31
|
|
|
32
32
|
RABBITMQ_USER = 'rabbitmq_user'
|
|
33
33
|
RABBITMQ_PASS = 'rabbitmq_pass'
|
|
@@ -199,7 +199,7 @@ class AbstractPublisher(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
199
199
|
|
|
200
200
|
def _convert_msg(self, msg: typing.Union[str, dict], task_id=None,
|
|
201
201
|
priority_control_config: PriorityConsumingControlConfig = None) -> (typing.Dict, typing.Dict, typing.Dict):
|
|
202
|
-
if isinstance(msg, (str,bytes)):
|
|
202
|
+
if isinstance(msg, (str, bytes)):
|
|
203
203
|
msg = json.loads(msg)
|
|
204
204
|
msg_function_kw = copy.deepcopy(msg)
|
|
205
205
|
raw_extra = {}
|
|
@@ -215,7 +215,7 @@ class AbstractPublisher(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
215
215
|
extra_params.update(priority_control_config.to_dict())
|
|
216
216
|
extra_params.update(raw_extra)
|
|
217
217
|
msg['extra'] = extra_params
|
|
218
|
-
return msg, msg_function_kw, extra_params,task_id
|
|
218
|
+
return msg, msg_function_kw, extra_params, task_id
|
|
219
219
|
|
|
220
220
|
def publish(self, msg: typing.Union[str, dict], task_id=None,
|
|
221
221
|
priority_control_config: PriorityConsumingControlConfig = None):
|
|
@@ -226,7 +226,7 @@ class AbstractPublisher(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
226
226
|
:param priority_control_config:优先级配置,消息可以携带优先级配置,覆盖boost的配置。
|
|
227
227
|
:return:
|
|
228
228
|
"""
|
|
229
|
-
msg, msg_function_kw, extra_params,task_id = self._convert_msg(msg, task_id, priority_control_config)
|
|
229
|
+
msg, msg_function_kw, extra_params, task_id = self._convert_msg(msg, task_id, priority_control_config)
|
|
230
230
|
t_start = time.time()
|
|
231
231
|
decorators.handle_exception(retry_times=10, is_throw_error=True, time_sleep=0.1)(
|
|
232
232
|
self.concrete_realization_of_publish)(json.dumps(msg, ensure_ascii=False))
|
|
@@ -3,11 +3,7 @@
|
|
|
3
3
|
# @Time : 2022/8/8 0008 12:12
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
|
-
import uuid
|
|
7
|
-
import copy
|
|
8
6
|
import time
|
|
9
|
-
import threading
|
|
10
|
-
import json
|
|
11
7
|
import celery
|
|
12
8
|
import celery.result
|
|
13
9
|
import typing
|
|
@@ -20,24 +16,6 @@ class CeleryPublisher(AbstractPublisher, ):
|
|
|
20
16
|
"""
|
|
21
17
|
使用celery作为中间件
|
|
22
18
|
"""
|
|
23
|
-
celery_conf_lock = threading.Lock()
|
|
24
|
-
|
|
25
|
-
# noinspection PyAttributeOutsideInit
|
|
26
|
-
def custom_init(self):
|
|
27
|
-
# self.broker_exclusive_config['task_routes'] = {self.queue_name: {"queue": self.queue_name}}
|
|
28
|
-
# celery_app.config_from_object(self.broker_exclusive_config)
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
|
-
# celery_app.conf.task_routes.update({self.queue_name: {"queue": self.queue_name}})
|
|
32
|
-
#
|
|
33
|
-
# @celery_app.task(name=self.queue_name)
|
|
34
|
-
# def f(*args, **kwargs):
|
|
35
|
-
# pass
|
|
36
|
-
#
|
|
37
|
-
# self._celery_app = celery_app
|
|
38
|
-
# self._celery_fun = f
|
|
39
|
-
|
|
40
|
-
celery_app.conf.task_routes.update({self.queue_name: {"queue": self.queue_name}})
|
|
41
19
|
|
|
42
20
|
def publish(self, msg: typing.Union[str, dict], task_id=None,
|
|
43
21
|
priority_control_config: PriorityConsumingControlConfig = None) -> celery.result.AsyncResult:
|
|
@@ -9,10 +9,11 @@ from threading import Lock
|
|
|
9
9
|
|
|
10
10
|
from funboost import funboost_config_deafult
|
|
11
11
|
from funboost.publishers.base_publisher import AbstractPublisher
|
|
12
|
+
from funboost.publishers.redis_queue_flush import FlushRedisQueueMixin
|
|
12
13
|
from funboost.utils import RedisMixin, decorators
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
class RedisPublisher(AbstractPublisher, RedisMixin):
|
|
16
|
+
class RedisPublisher(FlushRedisQueueMixin, AbstractPublisher, RedisMixin, ):
|
|
16
17
|
"""
|
|
17
18
|
使用redis作为中间件,这个是大幅优化了发布速度的方式。简单的发布是 redis_publisher_0000.py 中的代码方式。
|
|
18
19
|
|
|
@@ -42,7 +43,7 @@ class RedisPublisher(AbstractPublisher, RedisMixin):
|
|
|
42
43
|
# print(getattr(frame_config,'has_start_a_consumer_flag',0))
|
|
43
44
|
# 这里的 has_start_a_consumer_flag 是一个标志,借用此模块设置的一个标识变量而已,框架运行时候自动设定的,不要把这个变量写到模块里面。
|
|
44
45
|
# if getattr(funboost_config_deafult, 'has_start_a_consumer_flag', 0) == 0: # 加快速度推送,否则每秒只能推送4000次。如果是独立脚本推送,使用批量推送,如果是消费者中发布任务,为了保持原子性,用原来的单个推送。
|
|
45
|
-
if self.broker_exclusive_config.get('redis_bulk_push',0) == 1:
|
|
46
|
+
if self.broker_exclusive_config.get('redis_bulk_push', 0) == 1: # RedisConsumer传了, RedisAckAble 没传
|
|
46
47
|
# self._temp_msg_queue.put(msg)
|
|
47
48
|
with self._lock_for_bulk_push:
|
|
48
49
|
self._temp_msg_list.append(msg)
|
|
@@ -53,17 +54,6 @@ class RedisPublisher(AbstractPublisher, RedisMixin):
|
|
|
53
54
|
getattr(self.redis_db_frame, self._push_method)(self._queue_name, msg)
|
|
54
55
|
# print(msg)
|
|
55
56
|
|
|
56
|
-
# self.redis_db_frame.rpush(self._queue_name, msg)
|
|
57
|
-
def clear(self):
|
|
58
|
-
self.redis_db_frame.delete(self._queue_name)
|
|
59
|
-
# self.redis_db_frame.delete(f'{self._queue_name}__unack')
|
|
60
|
-
unack_queue_name_list = self.redis_db_frame.scan(match=f'{self._queue_name}__unack_id_*', count=10000)[1] + \
|
|
61
|
-
self.redis_db_frame.scan(match=f'unack_{self._queue_name}_*', count=10000)[1] # noqa
|
|
62
|
-
self.logger.warning(f'清除 {self._queue_name} 队列中的消息成功')
|
|
63
|
-
if unack_queue_name_list:
|
|
64
|
-
self.redis_db_frame.delete(*unack_queue_name_list)
|
|
65
|
-
self.logger.warning(f'清除 {unack_queue_name_list} 队列中的消息成功')
|
|
66
|
-
|
|
67
57
|
def get_message_count(self):
|
|
68
58
|
# print(self.redis_db7,self._queue_name)
|
|
69
59
|
return self.redis_db_frame.llen(self._queue_name)
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
# @Time : 2022/8/8 0008 12:12
|
|
4
4
|
|
|
5
5
|
from funboost.publishers.base_publisher import AbstractPublisher
|
|
6
|
+
from funboost.publishers.redis_queue_flush import FlushRedisQueueMixin
|
|
6
7
|
from funboost.utils.redis_manager import RedisMixin
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class RedisPriorityPublisher(AbstractPublisher, RedisMixin):
|
|
10
|
+
class RedisPriorityPublisher(FlushRedisQueueMixin,AbstractPublisher, RedisMixin,):
|
|
10
11
|
"""
|
|
11
12
|
redis队列,支持任务优先级。
|
|
12
13
|
"""
|
|
@@ -39,10 +40,6 @@ class RedisPriorityPublisher(AbstractPublisher, RedisMixin):
|
|
|
39
40
|
self.logger.debug([queue_name, msg])
|
|
40
41
|
self.redis_db_frame.rpush(queue_name, msg)
|
|
41
42
|
|
|
42
|
-
def clear(self):
|
|
43
|
-
self.redis_db_frame.delete(*self.queue_list)
|
|
44
|
-
self.redis_db_frame.delete(f'{self._queue_name}__unack')
|
|
45
|
-
self.logger.warning(f'清除 {self._queue_name} 队列中的消息成功')
|
|
46
43
|
|
|
47
44
|
def get_message_count(self):
|
|
48
45
|
count = 0
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
# @Author : ydf
|
|
3
3
|
# @Time : 2023/8/8 0008 12:12
|
|
4
4
|
from funboost.publishers.base_publisher import AbstractPublisher
|
|
5
|
+
from funboost.publishers.redis_queue_flush import FlushRedisQueueMixin
|
|
5
6
|
from funboost.utils import RedisMixin
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
class RedisPublisher(AbstractPublisher, RedisMixin):
|
|
9
|
+
class RedisPublisher(FlushRedisQueueMixin, AbstractPublisher, RedisMixin, ):
|
|
9
10
|
"""
|
|
10
11
|
使用redis作为中间件
|
|
11
12
|
"""
|
|
@@ -13,11 +14,6 @@ class RedisPublisher(AbstractPublisher, RedisMixin):
|
|
|
13
14
|
def concrete_realization_of_publish(self, msg):
|
|
14
15
|
self.redis_db_frame.rpush(self._queue_name, msg)
|
|
15
16
|
|
|
16
|
-
def clear(self):
|
|
17
|
-
self.redis_db_frame.delete(self._queue_name)
|
|
18
|
-
self.redis_db_frame.delete(f'{self._queue_name}__unack')
|
|
19
|
-
self.logger.warning(f'清除 {self._queue_name} 队列中的消息成功')
|
|
20
|
-
|
|
21
17
|
def get_message_count(self):
|
|
22
18
|
# nb_print(self.redis_db7,self._queue_name)
|
|
23
19
|
return self.redis_db_frame.llen(self._queue_name)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class FlushRedisQueueMixin:
|
|
2
|
+
# noinspection PyUnresolvedReferences
|
|
3
|
+
def clear(self):
|
|
4
|
+
self.redis_db_frame.delete(self._queue_name)
|
|
5
|
+
self.logger.warning(f'清除 {self._queue_name} 队列中的消息成功')
|
|
6
|
+
# self.redis_db_frame.delete(f'{self._queue_name}__unack')
|
|
7
|
+
unack_queue_name_list = self.redis_db_frame.scan(match=f'{self._queue_name}__unack_id_*', count=100000)[1] + \
|
|
8
|
+
self.redis_db_frame.scan(match=f'unack_{self._queue_name}_*', count=100000)[1] # noqa
|
|
9
|
+
if unack_queue_name_list:
|
|
10
|
+
self.redis_db_frame.delete(*unack_queue_name_list)
|
|
11
|
+
self.logger.warning(f'清除 {unack_queue_name_list} 队列中的消息成功')
|
funboost/utils/redis_manager.py
CHANGED
|
@@ -14,7 +14,7 @@ class RedisManager(object):
|
|
|
14
14
|
if (host, port, db, password) not in self.__class__._pool_dict:
|
|
15
15
|
# print ('创建一个连接池')
|
|
16
16
|
self.__class__._pool_dict[(host, port, db, password)] = redis.ConnectionPool(host=host, port=port, db=db,
|
|
17
|
-
password=password)
|
|
17
|
+
password=password,max_connections=100)
|
|
18
18
|
self._r = redis.Redis(connection_pool=self._pool_dict[(host, port, db, password)])
|
|
19
19
|
self._ping()
|
|
20
20
|
|
|
@@ -41,7 +41,7 @@ class RedisMixin(object):
|
|
|
41
41
|
@decorators.cached_method_result
|
|
42
42
|
def redis_db0(self):
|
|
43
43
|
return RedisManager(host=funboost_config_deafult.REDIS_HOST, port=funboost_config_deafult.REDIS_PORT,
|
|
44
|
-
password=funboost_config_deafult.REDIS_PASSWORD, db=0).get_redis()
|
|
44
|
+
password=funboost_config_deafult.REDIS_PASSWORD, db=0,).get_redis()
|
|
45
45
|
|
|
46
46
|
@property
|
|
47
47
|
@decorators.cached_method_result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: funboost
|
|
3
|
-
Version: 23.
|
|
3
|
+
Version: 23.7
|
|
4
4
|
Summary: pip install funboost,python全功能分布式函数调度框架,。支持python所有类型的并发模式和一切知名消息队列中间件,python函数加速器,框架包罗万象,一统编程思维,兼容50% python业务场景,适用范围广。只需要一行代码即可分布式执行python一切函数,99%用过funboost的pythoner 感受是 方便 快速 强大,相见恨晚
|
|
5
5
|
Home-page: https://github.com/ydf0509/funboost
|
|
6
6
|
Author: bfzs
|
|
@@ -50,7 +50,7 @@ Requires-Dist: pikav1
|
|
|
50
50
|
Requires-Dist: redis2
|
|
51
51
|
Requires-Dist: redis3
|
|
52
52
|
Requires-Dist: redis
|
|
53
|
-
Requires-Dist: nb-log (>=
|
|
53
|
+
Requires-Dist: nb-log (>=9.1)
|
|
54
54
|
Requires-Dist: rocketmq
|
|
55
55
|
Requires-Dist: zmq
|
|
56
56
|
Requires-Dist: pyzmq
|
|
@@ -159,9 +159,11 @@ funboost 是 function_scheduling_distributed_framework的包名更新版本
|
|
|
159
159
|
|
|
160
160
|
## 1.1 安装方式
|
|
161
161
|
|
|
162
|
+
```
|
|
162
163
|
pip install funboost --upgrade
|
|
163
164
|
|
|
164
|
-
|
|
165
|
+
或pip install funboost[extra_brokers] 一次性安装所有小众三方中间件
|
|
166
|
+
```
|
|
165
167
|
|
|
166
168
|
## 1.2 框架功能介绍
|
|
167
169
|
|
|
@@ -331,6 +333,12 @@ python通用分布式函数调度框架。适用场景范围广泛, 框架非
|
|
|
331
333
|
暂停消费:
|
|
332
334
|
支持从python解释器外部/远程机器 ,控制暂停消息消费和继续消费。
|
|
333
335
|
|
|
336
|
+
优先级队列:
|
|
337
|
+
支持队列优先级消息。
|
|
338
|
+
|
|
339
|
+
远程杀死任务:
|
|
340
|
+
支持在发布端杀死正在运行的消息,发送杀死命令时候对还未取出的消息则放弃运行消息。
|
|
341
|
+
|
|
334
342
|
</pre>
|
|
335
343
|
|
|
336
344
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
funboost/__init__.py,sha256=
|
|
1
|
+
funboost/__init__.py,sha256=YKM0VVSXRcZJnQbuqkIjS3PnLJxxIjw1-1JjI13Nn3A,2401
|
|
2
2
|
funboost/__init__old.py,sha256=cSzw-ZQqtAAp5_-7eONXQT5fwz_JbZlRjDQPASDLUHk,20378
|
|
3
3
|
funboost/constant.py,sha256=tSdHQ8nrZH63jOKKZFtOfTo2melCsiMrk-O1lFcsIKA,6489
|
|
4
|
-
funboost/funboost_config_deafult.py,sha256=
|
|
4
|
+
funboost/funboost_config_deafult.py,sha256=mh9o91CgMC26glIWkw7489GxmJ7bibi4_oBMnv3SCNU,7430
|
|
5
5
|
funboost/set_frame_config.py,sha256=hz_38C-IXEulYpHQdr1fhsMcdEDCHIsF2la8MkHiIjA,9149
|
|
6
|
-
funboost/assist/celery_helper.py,sha256=
|
|
6
|
+
funboost/assist/celery_helper.py,sha256=ZJ8jNSC-D8fE6pjxMVGAAA4j9i0gA1kVH14_BbTkXaQ,4569
|
|
7
7
|
funboost/assist/dramatiq_helper.py,sha256=lRNouO8MyCB_Qj2ppYG4FbMpf-2Aok8QhtGZLH1zWkg,2089
|
|
8
8
|
funboost/assist/huey_helper.py,sha256=VEzMdQDVJJ-ujcOXKw7chrTgvieLz4si3hrjt8gIK38,1760
|
|
9
9
|
funboost/assist/rq_helper.py,sha256=-tUZ00FzkczwBAkbbISPHF-8J0K7HLSZsue39WiF-cM,1509
|
|
@@ -26,8 +26,8 @@ funboost/concurrent_pool/backup/async_pool_executor0223.py,sha256=iTxxJFk2lu1P9Z
|
|
|
26
26
|
funboost/concurrent_pool/backup/async_pool_executor_back.py,sha256=vIgUUyF4Zb0jIRPWgNPqyO09YEkQP32kkpGBldqm4qA,9568
|
|
27
27
|
funboost/concurrent_pool/backup/async_pool_executor_janus.py,sha256=OHMWJ9l3EYTpPpcrPrGGKd4K0tmQ2PN8HiX0Dta0EOo,5728
|
|
28
28
|
funboost/consumers/__init__.py,sha256=ZXY_6Kut1VYNQiF5aWEgIWobsW1ht9YUP0TdRZRWFqI,126
|
|
29
|
-
funboost/consumers/base_consumer.py,sha256=
|
|
30
|
-
funboost/consumers/celery_consumer.py,sha256=
|
|
29
|
+
funboost/consumers/base_consumer.py,sha256=8goq0tx2db0ErfMeuKuNe62K5SOI-4Io58_7-xs2-X8,86846
|
|
30
|
+
funboost/consumers/celery_consumer.py,sha256=l0UQbO_KmvhCLtMtUgoHxHtEqyBCIABykyVKj04lZPM,8815
|
|
31
31
|
funboost/consumers/celery_consumer000.py,sha256=8SF8ppHIMH-BIAHO0NyJYnSQxe_PcT6hv05e7DySG54,4574
|
|
32
32
|
funboost/consumers/confirm_mixin.py,sha256=oVBQ1RayIBFOzGNTJ69HdBR_kLd46xd0VfCOKfqDpLA,6033
|
|
33
33
|
funboost/consumers/dramatiq_consumer.py,sha256=kiHM1wpSZykYDomtSGZ2PlMInCDn_8GOGEHqHUD9m0o,2144
|
|
@@ -47,14 +47,14 @@ funboost/consumers/nsq_consumer.py,sha256=PaMRsP8oeRg0H_tq4FL7YhNUdOWAqJkjrwZWoY
|
|
|
47
47
|
funboost/consumers/peewee_conusmer.py,sha256=fbspeWbv6F3EsIIBAjkM_FNh2vMyrDsydju23WAVHvE,1238
|
|
48
48
|
funboost/consumers/persist_queue_consumer.py,sha256=8HzRcMFE6OKiF_CL3atC42Ien_yf5daG3LU38YBKWi0,1005
|
|
49
49
|
funboost/consumers/pulsar_consumer.py,sha256=2DuklBV5dSY-_gW2EpRWz8QSy-VjZclj0gJUvLTyJHA,2414
|
|
50
|
-
funboost/consumers/rabbitmq_amqpstorm_consumer.py,sha256=
|
|
50
|
+
funboost/consumers/rabbitmq_amqpstorm_consumer.py,sha256=JJnSvewyWJDjAZmBi23r9PYUkt01knHfpRFjpmasjVw,2049
|
|
51
51
|
funboost/consumers/rabbitmq_pika_consumer.py,sha256=9L7CA2wYT-RNpaVfLKrFk6UJtONEIlfuDZYCjxHDOtc,5433
|
|
52
52
|
funboost/consumers/rabbitmq_pika_consumerv0.py,sha256=Yr-GJlgtkYB4qx8hKZZRx8PyCGwKAlSvRFKEf-SBXnM,4674
|
|
53
53
|
funboost/consumers/rabbitmq_rabbitpy_consumer.py,sha256=q-DXy2MHgsFfBssVIlqgziFw2jPkxAT4TyeDnlE0zwI,1260
|
|
54
54
|
funboost/consumers/redis_brpoplpush_consumer.py,sha256=rVdlmODLEQ8_k-gXFnaMFK8LaiKu3EiZMG2q5jmG8qk,3031
|
|
55
55
|
funboost/consumers/redis_consumer.py,sha256=f9nASEQUR3VHk5JH5Plf3RqKXmxogfrshu63RaFnfDM,2829
|
|
56
|
-
funboost/consumers/redis_consumer_ack_able.py,sha256=
|
|
57
|
-
funboost/consumers/redis_consumer_priority.py,sha256=
|
|
56
|
+
funboost/consumers/redis_consumer_ack_able.py,sha256=7bdG2282POZ_nbtMK2aAgYi43jNNXbw56uG0eUIII7M,7545
|
|
57
|
+
funboost/consumers/redis_consumer_priority.py,sha256=2BnNvsbNPZCRHdRxrnh1C3mJlqTgb1ql7xRn4-cHULU,5827
|
|
58
58
|
funboost/consumers/redis_consumer_simple.py,sha256=9D3uvLw_9WOmLmwys1K39DK3gj1ex_q6NXadXwyGwrs,922
|
|
59
59
|
funboost/consumers/redis_filter.py,sha256=TVyT2i9JhmhsJFyQZDx98phTiwBccNTl9fcErEDGXTM,7135
|
|
60
60
|
funboost/consumers/redis_pubsub_consumer.py,sha256=eSy5QBMPaouiQbeGQ3ZaLVpU1BF8g3B_4CAJHFqhmmI,1206
|
|
@@ -82,6 +82,7 @@ funboost/core/helper_funs.py,sha256=SKSMKytJTOFQJsuMKWJ-_mQg6e_Bgpq1ANDzjjBAcio,
|
|
|
82
82
|
funboost/core/kill_remote_task.py,sha256=Rj4nrz13CKka8he1T8-k6CYN_yjvcaYZaZ7yurKcKzo,8159
|
|
83
83
|
funboost/core/msg_result_getter.py,sha256=a2ffSE8Rvz1t1KVEt4UxIPsWgcriaHE_Armkac-JrJY,7782
|
|
84
84
|
funboost/core/muliti_process_enhance.py,sha256=zNodv3Ww5yCmwO6xCh7k8HntFHjIYYJ9EPaGinvPV9Q,3814
|
|
85
|
+
funboost/core/show_funboost_flag.py,sha256=EouUN_ioNXWaguA9qKQJKw1xYJqa1aLNxtd9SvL6g8A,5725
|
|
85
86
|
funboost/factories/__init__.py,sha256=s7kKKjR1HU5eMjPD6r5b-SXTVMo1zBp2JjOAtkyt5Yo,178
|
|
86
87
|
funboost/factories/broker_kind__publsiher_consumer_type_map.py,sha256=Ig1Kze8keS04_vXMNenZSDxibBSjxVrcMkDHviPsxnQ,8976
|
|
87
88
|
funboost/factories/consumer_factory.py,sha256=KFvYkx1a7egtSiTLuVsoRMKLUAotx-QJX1jAI8Xzo3s,946
|
|
@@ -102,8 +103,8 @@ funboost/function_result_web/static/js/jquery-1.11.0.min.js,sha256=ryQZ3RXgnqkTz
|
|
|
102
103
|
funboost/function_result_web/templates/index.html,sha256=dWe-JFQhsDpoNjSsBF4P6SJWp_KvHX8EP_yECS5r7_o,19501
|
|
103
104
|
funboost/function_result_web/templates/login.html,sha256=q37dj7O0LeyiV38Zd5P1Qn_qmhjdFomuYTRY1Yk48Bo,2007
|
|
104
105
|
funboost/publishers/__init__.py,sha256=xqBHlvsJQVPfbdvP84G0LHmVB7-pFBS7vDnX1Uo9pVY,131
|
|
105
|
-
funboost/publishers/base_publisher.py,sha256=
|
|
106
|
-
funboost/publishers/celery_publisher.py,sha256=
|
|
106
|
+
funboost/publishers/base_publisher.py,sha256=uuchEFgHMUlY2fBtGwZFLAzeKiWa7_34UTocGADTt2c,15863
|
|
107
|
+
funboost/publishers/celery_publisher.py,sha256=ELT-JR8RtmmCpsxYqVTuuFeKMFZMuK9ROKXWHkGVEjE,2334
|
|
107
108
|
funboost/publishers/celery_publisher000.py,sha256=ag2s7MzPPrnNdza3u8vcbDJqtiqbQw4lJJzAVuJ6GF0,3897
|
|
108
109
|
funboost/publishers/confluent_kafka_publisher.py,sha256=cpbyWvZ0T_kM62LWeBKRUuEuMkJAKOof97UUMSz6-Dk,3541
|
|
109
110
|
funboost/publishers/dramatiq_publisher.py,sha256=RoZzfvkS5H-XXcmHGBomuvkQRQBlVyiaCdWpgy0LL9o,1410
|
|
@@ -124,11 +125,12 @@ funboost/publishers/pulsar_publisher.py,sha256=3BqDtywExvTIw1KZWG4kT1uz029uw2Ykn
|
|
|
124
125
|
funboost/publishers/rabbitmq_amqpstorm_publisher.py,sha256=C32sQZpjv1iJtFDD6g_q0wI7Arw9i0RDsRVVOBRKzi4,3137
|
|
125
126
|
funboost/publishers/rabbitmq_pika_publisher.py,sha256=jZZw3DUiZ4VqJ6FqZGdv7qo3F_ltzHuKsy_5-j4jkCs,2343
|
|
126
127
|
funboost/publishers/rabbitmq_rabbitpy_publisher.py,sha256=GGXPKxE6-mAjqMIKqwvR9d7L-zuJQcQoU9uRsQLNGas,1953
|
|
127
|
-
funboost/publishers/redis_publisher.py,sha256=
|
|
128
|
+
funboost/publishers/redis_publisher.py,sha256=FUxvvYvf73J2Im33MRJd-5dmjnccjAFHaTMd4rLvdNM,3358
|
|
128
129
|
funboost/publishers/redis_publisher_lpush.py,sha256=xEWuCTtbDcKFLTxGrECrbIVapFfUwqX2-GHenMClu-Q,278
|
|
129
|
-
funboost/publishers/redis_publisher_priority.py,sha256=
|
|
130
|
-
funboost/publishers/redis_publisher_simple.py,sha256=
|
|
131
|
-
funboost/publishers/redis_pubsub_publisher.py,sha256=
|
|
130
|
+
funboost/publishers/redis_publisher_priority.py,sha256=YJCIMdiY0Sdttc7Xv85V-2P1R7ZoX5hqWz7waoibioQ,1972
|
|
131
|
+
funboost/publishers/redis_publisher_simple.py,sha256=fzEurzFQxrTO6PlCONz4m1jQljwuN66spbj4tIJ3Y6c,740
|
|
132
|
+
funboost/publishers/redis_pubsub_publisher.py,sha256=BxVn31I-Rt6gHFSTqntpsajmsl0ZftgMJMtiZd1LMyA,723
|
|
133
|
+
funboost/publishers/redis_queue_flush.py,sha256=d-AgJiCuX25mOwP2gMorGbXCaLuFpqWO4jAJXJDBfk0,732
|
|
132
134
|
funboost/publishers/redis_stream_publisher.py,sha256=DLxFcTlze0IdYFoaRmTcY8GCOaRwbj4aBNbylkt9gRA,2037
|
|
133
135
|
funboost/publishers/rocketmq_publisher.py,sha256=vY82WgutDPsS9px6rukU1d3AexmsT_tqSS2dmX-Pw-c,2343
|
|
134
136
|
funboost/publishers/rq_publisher.py,sha256=ANHrYnPTEj7KF_D_ov2L7PAT9swl82kjDazFqN1ULBY,893
|
|
@@ -158,7 +160,7 @@ funboost/utils/monkey_patches.py,sha256=Q0_jKxOfFrSgrIDSuSZFrgNh6w_LRGaKAITghrIp
|
|
|
158
160
|
funboost/utils/mqtt_util.py,sha256=BfCmyYwI-B8VL9499_IuYlJDCbv6ZhwyWThMf8dANOU,3199
|
|
159
161
|
funboost/utils/paramiko_util.py,sha256=pu67zkgptqNSV9m2Lznezb3zF1AFYvkWJp_6DVKFSPU,4901
|
|
160
162
|
funboost/utils/rabbitmq_factory.py,sha256=NPzTwG-INZG9aJgkzp-QVk3TgV0rjiuTVT5lmRT77zg,2963
|
|
161
|
-
funboost/utils/redis_manager.py,sha256=
|
|
163
|
+
funboost/utils/redis_manager.py,sha256=0mkPxBFE4pBv22Zi9O0YN-txvlRHdpjpl0maW5M0QvM,4649
|
|
162
164
|
funboost/utils/resource_monitoring.py,sha256=vf1htYa3a4wlMfQqksvIINMw8laiXwG5N8NXU2Zm3qQ,5532
|
|
163
165
|
funboost/utils/restart_python.py,sha256=bFbV0_24ajL8hBwVRLxWe9v9kTwiX1fGLhXRroNnmgQ,1418
|
|
164
166
|
funboost/utils/show_funboost_flag.py,sha256=YPXtykSkRBJZ4ulOIAXiTAfpOmo9IsjePz9G9AEE6cg,2985
|
|
@@ -213,8 +215,8 @@ funboost/utils/pysnooper_ydf/utils.py,sha256=evSmGi_Oul7vSP47AJ0DLjFwoCYCfunJZ1m
|
|
|
213
215
|
funboost/utils/pysnooper_ydf/variables.py,sha256=QejRDESBA06KG9OH4sBT4J1M55eaU29EIHg8K_igaXo,3693
|
|
214
216
|
funboost/utils/times/__init__.py,sha256=z-KQTxXapfu2ScJxISGe7QGffASuyJYL6JGsLXxD6O0,2332
|
|
215
217
|
funboost/utils/times/version.py,sha256=JiZLGTB-HYyBOV4xS0rnx2K2OqVMTebUj30sZRbrleE,16
|
|
216
|
-
funboost-23.
|
|
217
|
-
funboost-23.
|
|
218
|
-
funboost-23.
|
|
219
|
-
funboost-23.
|
|
220
|
-
funboost-23.
|
|
218
|
+
funboost-23.7.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
219
|
+
funboost-23.7.dist-info/METADATA,sha256=5MXcCOlQJKBFQo_e0-J6t0Wl3TeNhn2-yFfGl2AR4-I,26928
|
|
220
|
+
funboost-23.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
221
|
+
funboost-23.7.dist-info/top_level.txt,sha256=K8WuKnS6MRcEWxP1NvbmCeujJq6TEfbsB150YROlRw0,9
|
|
222
|
+
funboost-23.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|