funboost 50.2__py3-none-any.whl → 50.4__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/constant.py +4 -0
- funboost/consumers/base_consumer.py +95 -96
- funboost/consumers/celery_consumer.py +1 -1
- funboost/consumers/dramatiq_consumer.py +0 -5
- funboost/consumers/grpc_consumer.py +2 -19
- funboost/consumers/http_consumer.py +107 -40
- funboost/consumers/http_consumer_aiohttp_old.py +113 -0
- funboost/consumers/huey_consumer.py +2 -5
- funboost/consumers/kafka_consumer.py +1 -6
- funboost/consumers/kafka_consumer_manually_commit.py +0 -1
- funboost/consumers/kombu_consumer.py +0 -39
- funboost/consumers/mysql_cdc_consumer.py +1 -3
- funboost/consumers/pulsar_consumer.py +10 -5
- funboost/consumers/rabbitmq_amqpstorm_consumer.py +7 -8
- funboost/consumers/rabbitmq_complex_routing_consumer.py +54 -0
- funboost/consumers/redis_consumer.py +1 -1
- funboost/consumers/redis_consumer_ack_able.py +1 -1
- funboost/consumers/redis_consumer_ack_using_timeout.py +2 -6
- funboost/consumers/redis_consumer_priority.py +1 -1
- funboost/consumers/redis_stream_consumer.py +1 -3
- funboost/consumers/tcp_consumer.py +1 -1
- funboost/consumers/udp_consumer.py +1 -1
- funboost/consumers/zeromq_consumer.py +1 -1
- funboost/contrib/save_function_result_status/__init__.py +0 -0
- funboost/contrib/{save_result_status_to_sqldb.py → save_function_result_status/save_result_status_to_sqldb.py} +8 -41
- funboost/contrib/save_function_result_status/save_result_status_use_dataset.py +47 -0
- funboost/core/booster.py +38 -3
- funboost/core/broker_kind__exclusive_config_default_define.py +229 -0
- funboost/core/funboost_time.py +10 -45
- funboost/core/func_params_model.py +28 -4
- funboost/core/helper_funs.py +9 -8
- funboost/core/msg_result_getter.py +27 -0
- funboost/factories/broker_kind__publsiher_consumer_type_map.py +13 -3
- funboost/funboost_config_deafult.py +0 -3
- funboost/function_result_web/templates/fun_result_table.html +1 -1
- funboost/publishers/base_publisher.py +8 -2
- funboost/publishers/http_publisher.py +20 -2
- funboost/publishers/rabbitmq_amqpstorm_publisher.py +8 -7
- funboost/publishers/rabbitmq_complex_routing_publisher.py +84 -0
- funboost/utils/redis_manager.py +11 -5
- {funboost-50.2.dist-info → funboost-50.4.dist-info}/METADATA +159 -98
- {funboost-50.2.dist-info → funboost-50.4.dist-info}/RECORD +46 -41
- {funboost-50.2.dist-info → funboost-50.4.dist-info}/WHEEL +1 -1
- funboost-50.2.dist-info/LICENSE +0 -203
- {funboost-50.2.dist-info → funboost-50.4.dist-info}/entry_points.txt +0 -0
- {funboost-50.2.dist-info → funboost-50.4.dist-info}/top_level.txt +0 -0
funboost/__init__.py
CHANGED
funboost/constant.py
CHANGED
|
@@ -27,6 +27,10 @@ class BrokerEnum:
|
|
|
27
27
|
RABBITMQ_AMQPSTORM = 'RABBITMQ_AMQPSTORM' # 使用 amqpstorm 包操作rabbitmq 作为 分布式消息队列,支持消费确认.强烈推荐这个作为funboost中间件。
|
|
28
28
|
RABBITMQ = RABBITMQ_AMQPSTORM
|
|
29
29
|
|
|
30
|
+
# 2025-10 内置新增, 支持rabbitmq 所有路由模式,包括 fanout,direct,topic,headers. 使用概念更复杂
|
|
31
|
+
# 用法见 test_frame/test_broker_rabbitmq/test_rabbitmq_complex_routing 中的demo代码.
|
|
32
|
+
RABBITMQ_COMPLEX_ROUTING = 'RABBITMQ_COMPLEX_ROUTING'
|
|
33
|
+
|
|
30
34
|
RABBITMQ_RABBITPY = 'RABBITMQ_RABBITPY' # 使用 rabbitpy 包操作rabbitmq 作为 分布式消息队列,支持消费确认,不建议使用
|
|
31
35
|
|
|
32
36
|
"""
|
|
@@ -13,6 +13,7 @@ import typing
|
|
|
13
13
|
import abc
|
|
14
14
|
import copy
|
|
15
15
|
from apscheduler.jobstores.memory import MemoryJobStore
|
|
16
|
+
from funboost.core.broker_kind__exclusive_config_default_define import generate_broker_exclusive_config
|
|
16
17
|
from funboost.core.funboost_time import FunboostTime
|
|
17
18
|
from pathlib import Path
|
|
18
19
|
# from multiprocessing import Process
|
|
@@ -41,7 +42,6 @@ from funboost.core.serialization import PickleHelper, Serialization
|
|
|
41
42
|
from funboost.core.task_id_logger import TaskIdLogger
|
|
42
43
|
from funboost.constant import FunctionKind
|
|
43
44
|
|
|
44
|
-
|
|
45
45
|
from nb_libs.path_helper import PathHelper
|
|
46
46
|
from nb_log import (get_logger, LoggerLevelSetterMixin, LogManager, is_main_process,
|
|
47
47
|
nb_log_config_default)
|
|
@@ -74,7 +74,7 @@ from funboost.consumers.redis_filter import RedisFilter, RedisImpermanencyFilter
|
|
|
74
74
|
from funboost.factories.publisher_factotry import get_publisher
|
|
75
75
|
|
|
76
76
|
from funboost.utils import decorators, time_util, redis_manager
|
|
77
|
-
from funboost.constant import ConcurrentModeEnum, BrokerEnum, ConstStrForClassMethod,RedisKeys
|
|
77
|
+
from funboost.constant import ConcurrentModeEnum, BrokerEnum, ConstStrForClassMethod, RedisKeys
|
|
78
78
|
from funboost.core import kill_remote_task
|
|
79
79
|
from funboost.core.exceptions import ExceptionForRequeue, ExceptionForPushToDlxqueue
|
|
80
80
|
|
|
@@ -93,7 +93,6 @@ class GlobalVars:
|
|
|
93
93
|
class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
94
94
|
time_interval_for_check_do_not_run_time = 60
|
|
95
95
|
BROKER_KIND = None
|
|
96
|
-
BROKER_EXCLUSIVE_CONFIG_DEFAULT = {} # 每种中间件的概念有所不同,用户可以从 broker_exclusive_config 中传递该种中间件特有的配置意义参数。
|
|
97
96
|
|
|
98
97
|
@property
|
|
99
98
|
@decorators.synchronized
|
|
@@ -164,11 +163,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
164
163
|
filter_class = RedisFilter if consumer_params.task_filtering_expire_seconds == 0 else RedisImpermanencyFilter
|
|
165
164
|
self._redis_filter = filter_class(self._redis_filter_key_name, consumer_params.task_filtering_expire_seconds)
|
|
166
165
|
self._redis_filter.delete_expire_filter_task_cycle()
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
# if self.consumer_params.concurrent_mode == ConcurrentModeEnum.ASYNC and self.consumer_params.specify_async_loop is None:
|
|
169
168
|
# self.consumer_params.specify_async_loop= get_or_create_event_loop()
|
|
170
169
|
self._lock_for_count_execute_task_times_every_unit_time = Lock()
|
|
171
|
-
|
|
170
|
+
|
|
172
171
|
# self._unit_time_for_count = 10 # 每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
173
172
|
# self._execute_task_times_every_unit_time = 0 # 每单位时间执行了多少次任务。
|
|
174
173
|
# self._execute_task_times_every_unit_time_fail =0 # 每单位时间执行了多少次任务失败。
|
|
@@ -189,12 +188,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
189
188
|
self.metric_calculation = MetricCalculation(self)
|
|
190
189
|
|
|
191
190
|
self._result_persistence_helper: ResultPersistenceHelper
|
|
192
|
-
self.
|
|
193
|
-
broker_exclusive_config_merge = dict()
|
|
194
|
-
broker_exclusive_config_merge.update(self.BROKER_EXCLUSIVE_CONFIG_DEFAULT)
|
|
195
|
-
broker_exclusive_config_merge.update(self.consumer_params.broker_exclusive_config)
|
|
196
|
-
# print(broker_exclusive_config_merge)
|
|
197
|
-
self.consumer_params.broker_exclusive_config = broker_exclusive_config_merge
|
|
191
|
+
self.consumer_params.broker_exclusive_config = generate_broker_exclusive_config(self.consumer_params.broker_kind,self.consumer_params.broker_exclusive_config,self.logger)
|
|
198
192
|
|
|
199
193
|
self._stop_flag = None
|
|
200
194
|
self._pause_flag = threading.Event() # 暂停消费标志,从reids读取
|
|
@@ -233,7 +227,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
233
227
|
|
|
234
228
|
self._has_start_delay_task_scheduler = False
|
|
235
229
|
self._consuming_function_is_asyncio = inspect.iscoroutinefunction(self.consuming_function)
|
|
236
|
-
|
|
230
|
+
|
|
237
231
|
# develop_logger.warning(consumer_params._log_filename)
|
|
238
232
|
# self.publisher_params = PublisherParams(queue_name=consumer_params.queue_name, consuming_function=consumer_params.consuming_function,
|
|
239
233
|
# broker_kind=self.BROKER_KIND, log_level=consumer_params.log_level,
|
|
@@ -244,6 +238,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
244
238
|
# broker_exclusive_config=self.consumer_params.broker_exclusive_config)
|
|
245
239
|
self.publisher_params = BaseJsonAbleModel.init_by_another_model(PublisherParams, self.consumer_params)
|
|
246
240
|
# print(self.publisher_params)
|
|
241
|
+
self.custom_init()
|
|
247
242
|
if is_main_process:
|
|
248
243
|
self.logger.info(f'{self.queue_name} consumer 的消费者配置:\n {self.consumer_params.json_str_value()}')
|
|
249
244
|
|
|
@@ -261,12 +256,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
261
256
|
:return:
|
|
262
257
|
"""
|
|
263
258
|
if self.consumer_params.is_send_consumer_hearbeat_to_redis:
|
|
264
|
-
RedisMixin().redis_db_frame.sadd(RedisKeys.FUNBOOST_ALL_QUEUE_NAMES,self.queue_name)
|
|
259
|
+
RedisMixin().redis_db_frame.sadd(RedisKeys.FUNBOOST_ALL_QUEUE_NAMES, self.queue_name)
|
|
265
260
|
RedisMixin().redis_db_frame.hmset(RedisKeys.FUNBOOST_QUEUE__CONSUMER_PARAMS,
|
|
266
|
-
|
|
267
|
-
RedisMixin().redis_db_frame.sadd(RedisKeys.FUNBOOST_ALL_IPS,nb_log_config_default.computer_ip)
|
|
268
|
-
|
|
269
|
-
|
|
261
|
+
{self.queue_name: self.consumer_params.json_str_value()})
|
|
262
|
+
RedisMixin().redis_db_frame.sadd(RedisKeys.FUNBOOST_ALL_IPS, nb_log_config_default.computer_ip)
|
|
263
|
+
|
|
270
264
|
def _build_logger(self):
|
|
271
265
|
logger_prefix = self.consumer_params.logger_prefix
|
|
272
266
|
if logger_prefix != '':
|
|
@@ -282,13 +276,6 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
282
276
|
formatter_template=FunboostCommonConfig.NB_LOG_FORMATER_INDEX_FOR_CONSUMER_AND_PUBLISHER, )
|
|
283
277
|
self.logger.info(f'队列 {self.queue_name} 的日志写入到 {nb_log_config_default.LOG_PATH} 文件夹的 {log_filename} 和 {nb_log.generate_error_file_name(log_filename)} 文件中')
|
|
284
278
|
|
|
285
|
-
def _check_broker_exclusive_config(self):
|
|
286
|
-
broker_exclusive_config_keys = self.BROKER_EXCLUSIVE_CONFIG_DEFAULT.keys()
|
|
287
|
-
if self.consumer_params.broker_exclusive_config:
|
|
288
|
-
if set(self.consumer_params.broker_exclusive_config.keys()).issubset(broker_exclusive_config_keys):
|
|
289
|
-
self.logger.info(f'当前消息队列中间件能支持特殊独有配置 {self.consumer_params.broker_exclusive_config.keys()}')
|
|
290
|
-
else:
|
|
291
|
-
self.logger.warning(f'当前消息队列中间件含有不支持的特殊配置 {self.consumer_params.broker_exclusive_config.keys()},能支持的特殊独有配置包括 {broker_exclusive_config_keys}')
|
|
292
279
|
|
|
293
280
|
def _check_monkey_patch(self):
|
|
294
281
|
if self.consumer_params.concurrent_mode == ConcurrentModeEnum.GEVENT:
|
|
@@ -406,20 +393,19 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
406
393
|
)
|
|
407
394
|
}
|
|
408
395
|
self._delay_task_scheduler = FunboostBackgroundSchedulerProcessJobsWithinRedisLock(timezone=FunboostCommonConfig.TIMEZONE, daemon=False,
|
|
409
|
-
|
|
410
|
-
|
|
396
|
+
jobstores=jobstores # push 方法的序列化带thredignn.lock
|
|
397
|
+
)
|
|
411
398
|
self._delay_task_scheduler.set_process_jobs_redis_lock_key(
|
|
412
399
|
RedisKeys.gen_funboost_apscheduler_redis_lock_key_by_queue_name(self.queue_name))
|
|
413
400
|
elif self.consumer_params.delay_task_apscheduler_jobstores_kind == 'memory':
|
|
414
401
|
jobstores = {"default": MemoryJobStore()}
|
|
415
402
|
self._delay_task_scheduler = FsdfBackgroundScheduler(timezone=FunboostCommonConfig.TIMEZONE, daemon=False,
|
|
416
|
-
|
|
417
|
-
|
|
403
|
+
jobstores=jobstores # push 方法的序列化带thredignn.lock
|
|
404
|
+
)
|
|
418
405
|
|
|
419
406
|
else:
|
|
420
407
|
raise Exception(f'delay_task_apsscheduler_jobstores_kind is error: {self.consumer_params.delay_task_apscheduler_jobstores_kind}')
|
|
421
408
|
|
|
422
|
-
|
|
423
409
|
# self._delay_task_scheduler.add_executor(ApschedulerThreadPoolExecutor(2)) # 只是运行submit任务到并发池,不需要很多线程。
|
|
424
410
|
# self._delay_task_scheduler.add_listener(self._apscheduler_job_miss, EVENT_JOB_MISSED)
|
|
425
411
|
self._delay_task_scheduler.start()
|
|
@@ -431,7 +417,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
431
417
|
@classmethod
|
|
432
418
|
def _push_apscheduler_task_to_broker(cls, queue_name, msg):
|
|
433
419
|
funboost_lazy_impoter.BoostersManager.get_or_create_booster_by_queue_name(queue_name).publish(msg)
|
|
434
|
-
|
|
420
|
+
|
|
435
421
|
@abc.abstractmethod
|
|
436
422
|
def _shedual_task(self):
|
|
437
423
|
"""
|
|
@@ -441,10 +427,23 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
441
427
|
调用 self._submit_task(msg) 方法把它交给我处理就行。”
|
|
442
428
|
|
|
443
429
|
所以无论获取消息是 拉模式 还是推模式 还是轮询模式,无论是是单条获取 还是多条批量多条获取,
|
|
444
|
-
|
|
430
|
+
无论是传统mq,kafka,还是数据库,还是socket grpc tcp,还是kombu,还是python任务框架 celery rq dramtiq,
|
|
431
|
+
还是文件系统 ,以及火热的 mysql cdc(数据变更捕获) ,都能轻松扩展任意东西作为funboost的中间件。
|
|
432
|
+
|
|
433
|
+
_shedual_task 是万物可作为broker的核心,没有任何东西作为不了broker,扩展性无敌.
|
|
445
434
|
|
|
446
435
|
:return:
|
|
447
436
|
"""
|
|
437
|
+
|
|
438
|
+
"""
|
|
439
|
+
反观celery,由于kombu强行模拟靠拢经典amqp协议,只有rabbitmq作为broker在celery最完美,
|
|
440
|
+
redis在celery作为broker,消费确认ack 使用visibility_timeout,方案简直太糟糕了,
|
|
441
|
+
强制断电重启程序,要么孤儿消息重回不及时,要么把长耗时消息错误的当做是孤儿消息无限懵逼死循环重新入队.
|
|
442
|
+
|
|
443
|
+
celery实现kafka作为broker,这个issue 提了十几年一直无法完美实现,这就是celery+kombu 的局限性.
|
|
444
|
+
更别说把 mysql cdc作为celery的broker 了,funboost的设计在这方面是吊打celery.
|
|
445
|
+
"""
|
|
446
|
+
|
|
448
447
|
raise NotImplementedError
|
|
449
448
|
|
|
450
449
|
def _convert_msg_before_run(self, msg: typing.Union[str, dict]) -> dict:
|
|
@@ -481,7 +480,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
481
480
|
if 'publish_time_format':
|
|
482
481
|
extra['publish_time_format'] = MsgGenerater.generate_publish_time_format()
|
|
483
482
|
return msg
|
|
484
|
-
|
|
483
|
+
|
|
485
484
|
def _user_convert_msg_before_run(self, msg: typing.Union[str, dict]) -> dict:
|
|
486
485
|
"""
|
|
487
486
|
用户也可以提前清洗数据
|
|
@@ -499,9 +498,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
499
498
|
function_only_params = delete_keys_and_return_new_dict(kw['body'], )
|
|
500
499
|
kw['function_only_params'] = function_only_params
|
|
501
500
|
if self._get_priority_conf(kw, 'do_task_filtering') and self._redis_filter.check_value_exists(
|
|
502
|
-
function_only_params,self._get_priority_conf(kw, 'filter_str')): # 对函数的参数进行检查,过滤已经执行过并且成功的任务。
|
|
501
|
+
function_only_params, self._get_priority_conf(kw, 'filter_str')): # 对函数的参数进行检查,过滤已经执行过并且成功的任务。
|
|
503
502
|
self.logger.warning(f'redis的 [{self._redis_filter_key_name}] 键 中 过滤任务 {kw["body"]}')
|
|
504
|
-
self._confirm_consume(kw)
|
|
503
|
+
self._confirm_consume(kw) # 不运行就必须确认消费,否则会发不能确认消费,导致消息队列中间件认为消息没有被消费。
|
|
505
504
|
return
|
|
506
505
|
publish_time = get_publish_time(kw['body'])
|
|
507
506
|
msg_expire_senconds_priority = self._get_priority_conf(kw, 'msg_expire_senconds')
|
|
@@ -520,7 +519,6 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
520
519
|
if msg_countdown:
|
|
521
520
|
run_date = FunboostTime(kw['body']['extra']['publish_time']).datetime_obj + datetime.timedelta(seconds=msg_countdown)
|
|
522
521
|
if msg_eta:
|
|
523
|
-
|
|
524
522
|
run_date = FunboostTime(msg_eta).datetime_obj
|
|
525
523
|
# print(run_date,time_util.DatetimeConverter().datetime_obj)
|
|
526
524
|
# print(run_date.timestamp(),time_util.DatetimeConverter().datetime_obj.timestamp())
|
|
@@ -543,7 +541,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
543
541
|
self._delay_task_scheduler.add_job(self._push_apscheduler_task_to_broker, 'date', run_date=run_date,
|
|
544
542
|
kwargs={'queue_name': self.queue_name, 'msg': msg_no_delay, },
|
|
545
543
|
misfire_grace_time=misfire_grace_time,
|
|
546
|
-
|
|
544
|
+
)
|
|
547
545
|
self._confirm_consume(kw)
|
|
548
546
|
|
|
549
547
|
else: # 普通任务
|
|
@@ -636,18 +634,21 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
636
634
|
"""
|
|
637
635
|
self._do_not_delete_extra_from_msg = True
|
|
638
636
|
|
|
639
|
-
def _frame_custom_record_process_info_func(self,current_function_result_status: FunctionResultStatus,kw:dict):
|
|
637
|
+
def _frame_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, kw: dict):
|
|
640
638
|
pass
|
|
641
639
|
|
|
642
|
-
def
|
|
640
|
+
async def _aio_frame_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, kw: dict):
|
|
643
641
|
pass
|
|
644
642
|
|
|
645
|
-
|
|
643
|
+
def user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, ): # 这个可以继承
|
|
646
644
|
pass
|
|
647
645
|
|
|
648
|
-
def
|
|
646
|
+
async def aio_user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, ): # 这个可以继承
|
|
647
|
+
pass
|
|
648
|
+
|
|
649
|
+
def _convert_real_function_only_params_by_conusuming_function_kind(self, function_only_params: dict, extra_params: dict):
|
|
649
650
|
"""对于实例方法和classmethod 方法, 从消息队列的消息恢复第一个入参, self 和 cls"""
|
|
650
|
-
can_not_json_serializable_keys = extra_params.get('can_not_json_serializable_keys',[])
|
|
651
|
+
can_not_json_serializable_keys = extra_params.get('can_not_json_serializable_keys', [])
|
|
651
652
|
if self.consumer_params.consuming_function_kind in [FunctionKind.CLASS_METHOD, FunctionKind.INSTANCE_METHOD]:
|
|
652
653
|
real_function_only_params = copy.copy(function_only_params)
|
|
653
654
|
method_first_param_name = None
|
|
@@ -707,7 +708,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
707
708
|
current_function_result_status.run_status = RunStatus.finish
|
|
708
709
|
self._result_persistence_helper.save_function_result_to_mongo(current_function_result_status)
|
|
709
710
|
if self._get_priority_conf(kw, 'do_task_filtering'):
|
|
710
|
-
self._redis_filter.add_a_value(function_only_params,self._get_priority_conf(kw, 'filter_str')) # 函数执行成功后,添加函数的参数排序后的键值对字符串到set中。
|
|
711
|
+
self._redis_filter.add_a_value(function_only_params, self._get_priority_conf(kw, 'filter_str')) # 函数执行成功后,添加函数的参数排序后的键值对字符串到set中。
|
|
711
712
|
if current_function_result_status.success is False and current_retry_times == max_retry_times:
|
|
712
713
|
log_msg = f'函数 {self.consuming_function.__name__} 达到最大重试次数 {self._get_priority_conf(kw, "max_retry_times")} 后,仍然失败, 入参是 {function_only_params} '
|
|
713
714
|
if self.consumer_params.is_push_to_dlx_queue_when_retry_max_times:
|
|
@@ -730,11 +731,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
730
731
|
p.execute()
|
|
731
732
|
|
|
732
733
|
with self._lock_for_count_execute_task_times_every_unit_time:
|
|
733
|
-
self.metric_calculation.cal(t_start_run_fun,current_function_result_status)
|
|
734
|
-
self._frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
735
|
-
self.user_custom_record_process_info_func(current_function_result_status,) # 两种方式都可以自定义,记录结果,建议继承方式,不使用boost中指定 user_custom_record_process_info_func
|
|
734
|
+
self.metric_calculation.cal(t_start_run_fun, current_function_result_status)
|
|
735
|
+
self._frame_custom_record_process_info_func(current_function_result_status, kw)
|
|
736
|
+
self.user_custom_record_process_info_func(current_function_result_status, ) # 两种方式都可以自定义,记录结果,建议继承方式,不使用boost中指定 user_custom_record_process_info_func
|
|
736
737
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
737
|
-
self.consumer_params.user_custom_record_process_info_func(current_function_result_status,)
|
|
738
|
+
self.consumer_params.user_custom_record_process_info_func(current_function_result_status, )
|
|
738
739
|
except BaseException as e:
|
|
739
740
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
740
741
|
# self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
@@ -749,12 +750,12 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
749
750
|
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
750
751
|
task_id = kw['body']['extra']['task_id']
|
|
751
752
|
t_start = time.time()
|
|
752
|
-
|
|
753
|
+
|
|
753
754
|
fct = funboost_current_task()
|
|
754
755
|
fct_context = FctContext(function_params=function_only_params,
|
|
755
756
|
full_msg=kw['body'],
|
|
756
757
|
function_result_status=function_result_status,
|
|
757
|
-
logger=self.logger, queue_name=self.queue_name,)
|
|
758
|
+
logger=self.logger, queue_name=self.queue_name, )
|
|
758
759
|
|
|
759
760
|
try:
|
|
760
761
|
function_run = self.consuming_function
|
|
@@ -776,7 +777,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
776
777
|
self.logger.warning(f'取消运行 {task_id} {function_only_params}')
|
|
777
778
|
return function_result_status
|
|
778
779
|
function_run = kill_remote_task.kill_fun_deco(task_id)(function_run) # 用杀死装饰器包装起来在另一个线程运行函数,以便等待远程杀死。
|
|
779
|
-
function_result_status.result = function_run(**self._convert_real_function_only_params_by_conusuming_function_kind(function_only_params,kw['body']['extra']))
|
|
780
|
+
function_result_status.result = function_run(**self._convert_real_function_only_params_by_conusuming_function_kind(function_only_params, kw['body']['extra']))
|
|
780
781
|
# if asyncio.iscoroutine(function_result_status.result):
|
|
781
782
|
# log_msg = f'''异步的协程消费函数必须使用 async 并发模式并发,请设置消费函数 {self.consuming_function.__name__} 的concurrent_mode 为 ConcurrentModeEnum.ASYNC 或 4'''
|
|
782
783
|
# # self.logger.critical(msg=f'{log_msg} \n')
|
|
@@ -836,11 +837,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
836
837
|
|
|
837
838
|
function_result_status.result = FunctionResultStatus.FUNC_RUN_ERROR
|
|
838
839
|
return function_result_status
|
|
839
|
-
|
|
840
|
+
|
|
840
841
|
def _gen_asyncio_objects(self):
|
|
841
842
|
if getattr(self, '_async_lock_for_count_execute_task_times_every_unit_time', None) is None:
|
|
842
843
|
self._async_lock_for_count_execute_task_times_every_unit_time = asyncio.Lock()
|
|
843
|
-
|
|
844
|
+
|
|
844
845
|
# noinspection PyProtectedMember
|
|
845
846
|
async def _async_run(self, kw: dict, ):
|
|
846
847
|
"""
|
|
@@ -895,7 +896,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
895
896
|
await simple_run_in_executor(self._result_persistence_helper.save_function_result_to_mongo, current_function_result_status)
|
|
896
897
|
if self._get_priority_conf(kw, 'do_task_filtering'):
|
|
897
898
|
# self._redis_filter.add_a_value(function_only_params) # 函数执行成功后,添加函数的参数排序后的键值对字符串到set中。
|
|
898
|
-
await simple_run_in_executor(self._redis_filter.add_a_value, function_only_params,self._get_priority_conf(kw, 'filter_str'))
|
|
899
|
+
await simple_run_in_executor(self._redis_filter.add_a_value, function_only_params, self._get_priority_conf(kw, 'filter_str'))
|
|
899
900
|
if current_function_result_status.success is False and current_retry_times == max_retry_times:
|
|
900
901
|
log_msg = f'函数 {self.consuming_function.__name__} 达到最大重试次数 {self._get_priority_conf(kw, "max_retry_times")} 后,仍然失败, 入参是 {function_only_params} '
|
|
901
902
|
if self.consumer_params.is_push_to_dlx_queue_when_retry_max_times:
|
|
@@ -920,11 +921,12 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
920
921
|
async with self._async_lock_for_count_execute_task_times_every_unit_time:
|
|
921
922
|
self.metric_calculation.cal(t_start_run_fun, current_function_result_status)
|
|
922
923
|
|
|
923
|
-
self._frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
924
|
-
self.
|
|
925
|
-
|
|
924
|
+
self._frame_custom_record_process_info_func(current_function_result_status, kw)
|
|
925
|
+
await self._aio_frame_custom_record_process_info_func(current_function_result_status, kw)
|
|
926
|
+
self.user_custom_record_process_info_func(current_function_result_status, ) # 两种方式都可以自定义,记录结果.建议使用文档4.21.b的方式继承来重写
|
|
927
|
+
await self.aio_user_custom_record_process_info_func(current_function_result_status, )
|
|
926
928
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
927
|
-
self.consumer_params.user_custom_record_process_info_func(current_function_result_status,)
|
|
929
|
+
self.consumer_params.user_custom_record_process_info_func(current_function_result_status, )
|
|
928
930
|
|
|
929
931
|
except BaseException as e:
|
|
930
932
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
@@ -940,17 +942,17 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
940
942
|
"""虽然和上面有点大面积重复相似,这个是为了asyncio模式的,asyncio模式真的和普通同步模式的代码思维和形式区别太大,
|
|
941
943
|
框架实现兼容async的消费函数很麻烦复杂,连并发池都要单独写"""
|
|
942
944
|
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
943
|
-
|
|
945
|
+
|
|
944
946
|
# noinspection PyBroadException
|
|
945
947
|
t_start = time.time()
|
|
946
948
|
fct = funboost_current_task()
|
|
947
949
|
fct_context = FctContext(function_params=function_only_params,
|
|
948
950
|
full_msg=kw['body'],
|
|
949
951
|
function_result_status=function_result_status,
|
|
950
|
-
logger=self.logger,queue_name=self.queue_name,)
|
|
952
|
+
logger=self.logger, queue_name=self.queue_name, )
|
|
951
953
|
fct.set_fct_context(fct_context)
|
|
952
954
|
try:
|
|
953
|
-
corotinue_obj = self.consuming_function(**self._convert_real_function_only_params_by_conusuming_function_kind(function_only_params,kw['body']['extra']))
|
|
955
|
+
corotinue_obj = self.consuming_function(**self._convert_real_function_only_params_by_conusuming_function_kind(function_only_params, kw['body']['extra']))
|
|
954
956
|
if not asyncio.iscoroutine(corotinue_obj):
|
|
955
957
|
log_msg = f'''当前设置的并发模式为 async 并发模式,但消费函数不是异步协程函数,请不要把消费函数 {self.consuming_function.__name__} 的 concurrent_mode 设置错误'''
|
|
956
958
|
# self.logger.critical(msg=f'{log_msg} \n')
|
|
@@ -1054,11 +1056,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
1054
1056
|
|
|
1055
1057
|
def pause_consume(self):
|
|
1056
1058
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动停止消费,此功能需要配置好redis"""
|
|
1057
|
-
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name,'1')
|
|
1059
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name, '1')
|
|
1058
1060
|
|
|
1059
1061
|
def continue_consume(self):
|
|
1060
1062
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动继续消费,此功能需要配置好redis"""
|
|
1061
|
-
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name,'0')
|
|
1063
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name, '0')
|
|
1062
1064
|
|
|
1063
1065
|
@decorators.FunctionResultCacher.cached_function_result_for_a_time(120)
|
|
1064
1066
|
def _judge_is_daylight(self):
|
|
@@ -1160,8 +1162,8 @@ class ConcurrentModeDispatcher(FunboostFileLoggerMixin):
|
|
|
1160
1162
|
if self._concurrent_mode == ConcurrentModeEnum.ASYNC:
|
|
1161
1163
|
self.consumer._concurrent_pool = self.consumer.consumer_params.specify_concurrent_pool or pool_type(
|
|
1162
1164
|
self.consumer.consumer_params.concurrent_num,
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
+
specify_async_loop=self.consumer.consumer_params.specify_async_loop,
|
|
1166
|
+
is_auto_start_specify_async_loop_in_child_thread=self.consumer.consumer_params.is_auto_start_specify_async_loop_in_child_thread)
|
|
1165
1167
|
else:
|
|
1166
1168
|
# print(pool_type)
|
|
1167
1169
|
self.consumer._concurrent_pool = self.consumer.consumer_params.specify_concurrent_pool or pool_type(self.consumer.consumer_params.concurrent_num)
|
|
@@ -1208,14 +1210,14 @@ def wait_for_possible_has_finish_all_tasks_by_conusmer_list(consumer_list: typin
|
|
|
1208
1210
|
|
|
1209
1211
|
|
|
1210
1212
|
class MetricCalculation:
|
|
1211
|
-
UNIT_TIME_FOR_COUNT = 10
|
|
1213
|
+
UNIT_TIME_FOR_COUNT = 10 # 这个不要随意改,需要其他地方配合,每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
1212
1214
|
|
|
1213
|
-
def __init__(self,conusmer:AbstractConsumer) -> None:
|
|
1215
|
+
def __init__(self, conusmer: AbstractConsumer) -> None:
|
|
1214
1216
|
self.consumer = conusmer
|
|
1215
1217
|
|
|
1216
1218
|
self.unit_time_for_count = self.UNIT_TIME_FOR_COUNT #
|
|
1217
1219
|
self.execute_task_times_every_unit_time_temp = 0 # 每单位时间执行了多少次任务。
|
|
1218
|
-
self.execute_task_times_every_unit_time_temp_fail =0 # 每单位时间执行了多少次任务失败。
|
|
1220
|
+
self.execute_task_times_every_unit_time_temp_fail = 0 # 每单位时间执行了多少次任务失败。
|
|
1219
1221
|
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1220
1222
|
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1221
1223
|
self.last_execute_task_time = time.time() # 最近一次执行任务的时间。
|
|
@@ -1229,22 +1231,22 @@ class MetricCalculation:
|
|
|
1229
1231
|
self.last_timestamp_when_has_task_in_queue = 0
|
|
1230
1232
|
self.last_timestamp_print_msg_num = 0
|
|
1231
1233
|
|
|
1232
|
-
self.total_consume_count_from_start =0
|
|
1233
|
-
self.total_consume_count_from_start_fail =0
|
|
1234
|
+
self.total_consume_count_from_start = 0
|
|
1235
|
+
self.total_consume_count_from_start_fail = 0
|
|
1234
1236
|
self.total_cost_time_from_start = 0 # 函数运行累计花费时间
|
|
1235
1237
|
self.last_x_s_total_cost_time = None
|
|
1236
1238
|
|
|
1237
|
-
def cal(self,t_start_run_fun:float,current_function_result_status:FunctionResultStatus):
|
|
1239
|
+
def cal(self, t_start_run_fun: float, current_function_result_status: FunctionResultStatus):
|
|
1238
1240
|
self.last_execute_task_time = time.time()
|
|
1239
1241
|
current_msg_cost_time = time.time() - t_start_run_fun
|
|
1240
1242
|
self.execute_task_times_every_unit_time_temp += 1
|
|
1241
|
-
self.total_consume_count_from_start
|
|
1243
|
+
self.total_consume_count_from_start += 1
|
|
1242
1244
|
self.total_cost_time_from_start += current_msg_cost_time
|
|
1243
1245
|
if current_function_result_status.success is False:
|
|
1244
1246
|
self.execute_task_times_every_unit_time_temp_fail += 1
|
|
1245
|
-
self.total_consume_count_from_start_fail +=1
|
|
1247
|
+
self.total_consume_count_from_start_fail += 1
|
|
1246
1248
|
self.consuming_function_cost_time_total_every_unit_time_tmp += current_msg_cost_time
|
|
1247
|
-
|
|
1249
|
+
|
|
1248
1250
|
if time.time() - self.current_time_for_execute_task_times_every_unit_time > self.unit_time_for_count:
|
|
1249
1251
|
self.last_x_s_execute_count = self.execute_task_times_every_unit_time_temp
|
|
1250
1252
|
self.last_x_s_execute_count_fail = self.execute_task_times_every_unit_time_temp_fail
|
|
@@ -1263,30 +1265,30 @@ class MetricCalculation:
|
|
|
1263
1265
|
self.consumer.logger.info(msg)
|
|
1264
1266
|
self.last_show_remaining_execution_time = time.time()
|
|
1265
1267
|
if self.consumer.consumer_params.is_send_consumer_hearbeat_to_redis is True:
|
|
1266
|
-
RedisMixin().redis_db_frame.hincrby(RedisKeys.FUNBOOST_QUEUE__RUN_COUNT_MAP,self.consumer.queue_name,self.execute_task_times_every_unit_time_temp)
|
|
1267
|
-
RedisMixin().redis_db_frame.hincrby(RedisKeys.FUNBOOST_QUEUE__RUN_FAIL_COUNT_MAP,self.consumer.queue_name,self.execute_task_times_every_unit_time_temp_fail)
|
|
1268
|
+
RedisMixin().redis_db_frame.hincrby(RedisKeys.FUNBOOST_QUEUE__RUN_COUNT_MAP, self.consumer.queue_name, self.execute_task_times_every_unit_time_temp)
|
|
1269
|
+
RedisMixin().redis_db_frame.hincrby(RedisKeys.FUNBOOST_QUEUE__RUN_FAIL_COUNT_MAP, self.consumer.queue_name, self.execute_task_times_every_unit_time_temp_fail)
|
|
1268
1270
|
|
|
1269
1271
|
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1270
1272
|
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1271
1273
|
self.execute_task_times_every_unit_time_temp = 0
|
|
1272
1274
|
self.execute_task_times_every_unit_time_temp_fail = 0
|
|
1273
1275
|
|
|
1274
|
-
def get_report_hearbeat_info(self) ->dict:
|
|
1276
|
+
def get_report_hearbeat_info(self) -> dict:
|
|
1275
1277
|
return {
|
|
1276
|
-
'unit_time_for_count':self.unit_time_for_count,
|
|
1277
|
-
'last_x_s_execute_count':self.last_x_s_execute_count,
|
|
1278
|
-
'last_x_s_execute_count_fail':self.last_x_s_execute_count_fail,
|
|
1279
|
-
'last_execute_task_time':self.last_execute_task_time,
|
|
1280
|
-
'last_x_s_avarage_function_spend_time':self.last_x_s_avarage_function_spend_time,
|
|
1278
|
+
'unit_time_for_count': self.unit_time_for_count,
|
|
1279
|
+
'last_x_s_execute_count': self.last_x_s_execute_count,
|
|
1280
|
+
'last_x_s_execute_count_fail': self.last_x_s_execute_count_fail,
|
|
1281
|
+
'last_execute_task_time': self.last_execute_task_time,
|
|
1282
|
+
'last_x_s_avarage_function_spend_time': self.last_x_s_avarage_function_spend_time,
|
|
1281
1283
|
# 'last_show_remaining_execution_time':self.last_show_remaining_execution_time,
|
|
1282
|
-
'msg_num_in_broker':self.msg_num_in_broker,
|
|
1283
|
-
'current_time_for_execute_task_times_every_unit_time':self.current_time_for_execute_task_times_every_unit_time,
|
|
1284
|
-
'last_timestamp_when_has_task_in_queue':self.last_timestamp_when_has_task_in_queue,
|
|
1285
|
-
'total_consume_count_from_start':self.total_consume_count_from_start,
|
|
1286
|
-
'total_consume_count_from_start_fail':self.total_consume_count_from_start_fail,
|
|
1287
|
-
'total_cost_time_from_start':self.total_cost_time_from_start,
|
|
1288
|
-
'last_x_s_total_cost_time':self.last_x_s_total_cost_time,
|
|
1289
|
-
'avarage_function_spend_time_from_start':round(self.total_cost_time_from_start / self.total_consume_count_from_start,3) if self.total_consume_count_from_start else None,
|
|
1284
|
+
'msg_num_in_broker': self.msg_num_in_broker,
|
|
1285
|
+
'current_time_for_execute_task_times_every_unit_time': self.current_time_for_execute_task_times_every_unit_time,
|
|
1286
|
+
'last_timestamp_when_has_task_in_queue': self.last_timestamp_when_has_task_in_queue,
|
|
1287
|
+
'total_consume_count_from_start': self.total_consume_count_from_start,
|
|
1288
|
+
'total_consume_count_from_start_fail': self.total_consume_count_from_start_fail,
|
|
1289
|
+
'total_cost_time_from_start': self.total_cost_time_from_start,
|
|
1290
|
+
'last_x_s_total_cost_time': self.last_x_s_total_cost_time,
|
|
1291
|
+
'avarage_function_spend_time_from_start': round(self.total_cost_time_from_start / self.total_consume_count_from_start, 3) if self.total_consume_count_from_start else None,
|
|
1290
1292
|
}
|
|
1291
1293
|
|
|
1292
1294
|
|
|
@@ -1347,11 +1349,10 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1347
1349
|
p.sadd(redis_key, value)
|
|
1348
1350
|
p.execute()
|
|
1349
1351
|
|
|
1350
|
-
|
|
1351
1352
|
def _send_msg_num(self):
|
|
1352
|
-
dic = {'msg_num_in_broker':self._consumer.metric_calculation.msg_num_in_broker,
|
|
1353
|
-
'last_get_msg_num_ts':self._consumer.metric_calculation.last_get_msg_num_ts,
|
|
1354
|
-
'report_ts':time.time(),
|
|
1353
|
+
dic = {'msg_num_in_broker': self._consumer.metric_calculation.msg_num_in_broker,
|
|
1354
|
+
'last_get_msg_num_ts': self._consumer.metric_calculation.last_get_msg_num_ts,
|
|
1355
|
+
'report_ts': time.time(),
|
|
1355
1356
|
}
|
|
1356
1357
|
self.redis_db_frame.hset(RedisKeys.QUEUE__MSG_COUNT_MAP, self._consumer.queue_name, json.dumps(dic))
|
|
1357
1358
|
|
|
@@ -1387,16 +1388,14 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1387
1388
|
|
|
1388
1389
|
# noinspection PyProtectedMember
|
|
1389
1390
|
def _get_stop_and_pause_flag_from_redis(self):
|
|
1390
|
-
stop_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_STOP_FLAG,self._consumer.queue_name)
|
|
1391
|
+
stop_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_STOP_FLAG, self._consumer.queue_name)
|
|
1391
1392
|
if stop_flag is not None and int(stop_flag) == 1:
|
|
1392
1393
|
self._consumer._stop_flag = 1
|
|
1393
1394
|
else:
|
|
1394
1395
|
self._consumer._stop_flag = 0
|
|
1395
1396
|
|
|
1396
|
-
pause_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_PAUSE_FLAG,self._consumer.queue_name)
|
|
1397
|
+
pause_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_PAUSE_FLAG, self._consumer.queue_name)
|
|
1397
1398
|
if pause_flag is not None and int(pause_flag) == 1:
|
|
1398
1399
|
self._consumer._pause_flag.set()
|
|
1399
1400
|
else:
|
|
1400
1401
|
self._consumer._pause_flag.clear()
|
|
1401
|
-
|
|
1402
|
-
|
|
@@ -13,7 +13,7 @@ class CeleryConsumer(AbstractConsumer):
|
|
|
13
13
|
celery作为中间件实现的。
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
|
|
18
18
|
# celery的可以配置项大全 https://docs.celeryq.dev/en/stable/userguide/configuration.html#new-lowercase-settings
|
|
19
19
|
# celery @app.task() 所有可以配置项可以看 D:\ProgramData\Miniconda3\Lib\site-packages\celery\app\task.py
|
|
@@ -11,11 +11,6 @@ class DramatiqConsumer(AbstractConsumer):
|
|
|
11
11
|
dramatiq作为中间件实现的。
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
BROKER_EXCLUSIVE_CONFIG_DEFAULT = {'dramatiq_actor_options': {}}
|
|
15
|
-
"""
|
|
16
|
-
dramatiq_actor_options 的值可以是:
|
|
17
|
-
{'max_age', 'throws', 'pipe_target', 'pipe_ignore', 'on_success', 'retry_when', 'time_limit', 'min_backoff', 'max_retries', 'max_backoff', 'notify_shutdown', 'on_failure'}
|
|
18
|
-
"""
|
|
19
14
|
|
|
20
15
|
def custom_init(self):
|
|
21
16
|
# 这就是核心,
|
|
@@ -10,29 +10,12 @@ import time
|
|
|
10
10
|
from funboost import FunctionResultStatus
|
|
11
11
|
from funboost.assist.grpc_helper import funboost_grpc_pb2_grpc, funboost_grpc_pb2
|
|
12
12
|
from funboost.consumers.base_consumer import AbstractConsumer
|
|
13
|
+
from funboost.core.msg_result_getter import FutureStatusResult
|
|
13
14
|
from funboost.core.serialization import Serialization
|
|
14
15
|
from funboost.core.exceptions import FunboostWaitRpcResultTimeout
|
|
15
16
|
from funboost.concurrent_pool.flexible_thread_pool import FlexibleThreadPool
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class FutureStatusResult:
|
|
19
|
-
def __init__(self,call_type:str):
|
|
20
|
-
self.execute_finish_event = threading.Event()
|
|
21
|
-
self.staus_result_obj: FunctionResultStatus = None
|
|
22
|
-
self.call_type = call_type # sync_call or publish
|
|
23
|
-
|
|
24
|
-
def set_finish(self):
|
|
25
|
-
self.execute_finish_event.set()
|
|
26
|
-
|
|
27
|
-
def wait_finish(self,rpc_timeout):
|
|
28
|
-
return self.execute_finish_event.wait(rpc_timeout)
|
|
29
|
-
|
|
30
|
-
def set_staus_result_obj(self, staus_result_obj:FunctionResultStatus):
|
|
31
|
-
self.staus_result_obj = staus_result_obj
|
|
32
|
-
|
|
33
|
-
def get_staus_result_obj(self):
|
|
34
|
-
return self.staus_result_obj
|
|
35
|
-
|
|
36
19
|
|
|
37
20
|
|
|
38
21
|
|
|
@@ -40,7 +23,7 @@ class GrpcConsumer(AbstractConsumer, ):
|
|
|
40
23
|
"""
|
|
41
24
|
grpc as broker
|
|
42
25
|
"""
|
|
43
|
-
|
|
26
|
+
|
|
44
27
|
|
|
45
28
|
def custom_init(self):
|
|
46
29
|
class FunboostGrpcServicer(funboost_grpc_pb2_grpc.FunboostBrokerServiceServicer):
|