funboost 50.3__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 +93 -98
- funboost/consumers/celery_consumer.py +1 -1
- funboost/consumers/dramatiq_consumer.py +0 -5
- funboost/consumers/grpc_consumer.py +1 -1
- funboost/consumers/http_consumer.py +1 -1
- funboost/consumers/http_consumer_aiohttp_old.py +1 -1
- funboost/consumers/huey_consumer.py +2 -5
- funboost/consumers/kafka_consumer.py +0 -2
- 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 +7 -1
- funboost/core/broker_kind__exclusive_config_default_define.py +229 -0
- funboost/core/funboost_time.py +3 -82
- funboost/core/func_params_model.py +9 -3
- funboost/core/helper_funs.py +2 -2
- funboost/factories/broker_kind__publsiher_consumer_type_map.py +5 -0
- funboost/funboost_config_deafult.py +0 -3
- funboost/function_result_web/templates/fun_result_table.html +1 -1
- funboost/publishers/base_publisher.py +3 -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.3.dist-info → funboost-50.4.dist-info}/METADATA +156 -97
- {funboost-50.3.dist-info → funboost-50.4.dist-info}/RECORD +44 -40
- {funboost-50.3.dist-info → funboost-50.4.dist-info}/WHEEL +1 -1
- funboost-50.3.dist-info/LICENSE +0 -203
- {funboost-50.3.dist-info → funboost-50.4.dist-info}/entry_points.txt +0 -0
- {funboost-50.3.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,21 +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
|
-
async def _aio_frame_custom_record_process_info_func(self,current_function_result_status: FunctionResultStatus,kw:dict):
|
|
640
|
+
async def _aio_frame_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, kw: dict):
|
|
643
641
|
pass
|
|
644
642
|
|
|
645
|
-
def user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus,): # 这个可以继承
|
|
643
|
+
def user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, ): # 这个可以继承
|
|
646
644
|
pass
|
|
647
645
|
|
|
648
|
-
async def aio_user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus,): # 这个可以继承
|
|
646
|
+
async def aio_user_custom_record_process_info_func(self, current_function_result_status: FunctionResultStatus, ): # 这个可以继承
|
|
649
647
|
pass
|
|
650
648
|
|
|
651
|
-
def _convert_real_function_only_params_by_conusuming_function_kind(self, function_only_params: dict,extra_params:dict):
|
|
649
|
+
def _convert_real_function_only_params_by_conusuming_function_kind(self, function_only_params: dict, extra_params: dict):
|
|
652
650
|
"""对于实例方法和classmethod 方法, 从消息队列的消息恢复第一个入参, self 和 cls"""
|
|
653
|
-
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', [])
|
|
654
652
|
if self.consumer_params.consuming_function_kind in [FunctionKind.CLASS_METHOD, FunctionKind.INSTANCE_METHOD]:
|
|
655
653
|
real_function_only_params = copy.copy(function_only_params)
|
|
656
654
|
method_first_param_name = None
|
|
@@ -710,7 +708,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
710
708
|
current_function_result_status.run_status = RunStatus.finish
|
|
711
709
|
self._result_persistence_helper.save_function_result_to_mongo(current_function_result_status)
|
|
712
710
|
if self._get_priority_conf(kw, 'do_task_filtering'):
|
|
713
|
-
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中。
|
|
714
712
|
if current_function_result_status.success is False and current_retry_times == max_retry_times:
|
|
715
713
|
log_msg = f'函数 {self.consuming_function.__name__} 达到最大重试次数 {self._get_priority_conf(kw, "max_retry_times")} 后,仍然失败, 入参是 {function_only_params} '
|
|
716
714
|
if self.consumer_params.is_push_to_dlx_queue_when_retry_max_times:
|
|
@@ -733,11 +731,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
733
731
|
p.execute()
|
|
734
732
|
|
|
735
733
|
with self._lock_for_count_execute_task_times_every_unit_time:
|
|
736
|
-
self.metric_calculation.cal(t_start_run_fun,current_function_result_status)
|
|
737
|
-
self._frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
738
|
-
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
|
|
739
737
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
740
|
-
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, )
|
|
741
739
|
except BaseException as e:
|
|
742
740
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
743
741
|
# self.logger.critical(msg=f'{log_msg} \n', exc_info=True)
|
|
@@ -752,12 +750,12 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
752
750
|
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
753
751
|
task_id = kw['body']['extra']['task_id']
|
|
754
752
|
t_start = time.time()
|
|
755
|
-
|
|
753
|
+
|
|
756
754
|
fct = funboost_current_task()
|
|
757
755
|
fct_context = FctContext(function_params=function_only_params,
|
|
758
756
|
full_msg=kw['body'],
|
|
759
757
|
function_result_status=function_result_status,
|
|
760
|
-
logger=self.logger, queue_name=self.queue_name,)
|
|
758
|
+
logger=self.logger, queue_name=self.queue_name, )
|
|
761
759
|
|
|
762
760
|
try:
|
|
763
761
|
function_run = self.consuming_function
|
|
@@ -779,7 +777,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
779
777
|
self.logger.warning(f'取消运行 {task_id} {function_only_params}')
|
|
780
778
|
return function_result_status
|
|
781
779
|
function_run = kill_remote_task.kill_fun_deco(task_id)(function_run) # 用杀死装饰器包装起来在另一个线程运行函数,以便等待远程杀死。
|
|
782
|
-
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']))
|
|
783
781
|
# if asyncio.iscoroutine(function_result_status.result):
|
|
784
782
|
# log_msg = f'''异步的协程消费函数必须使用 async 并发模式并发,请设置消费函数 {self.consuming_function.__name__} 的concurrent_mode 为 ConcurrentModeEnum.ASYNC 或 4'''
|
|
785
783
|
# # self.logger.critical(msg=f'{log_msg} \n')
|
|
@@ -839,11 +837,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
839
837
|
|
|
840
838
|
function_result_status.result = FunctionResultStatus.FUNC_RUN_ERROR
|
|
841
839
|
return function_result_status
|
|
842
|
-
|
|
840
|
+
|
|
843
841
|
def _gen_asyncio_objects(self):
|
|
844
842
|
if getattr(self, '_async_lock_for_count_execute_task_times_every_unit_time', None) is None:
|
|
845
843
|
self._async_lock_for_count_execute_task_times_every_unit_time = asyncio.Lock()
|
|
846
|
-
|
|
844
|
+
|
|
847
845
|
# noinspection PyProtectedMember
|
|
848
846
|
async def _async_run(self, kw: dict, ):
|
|
849
847
|
"""
|
|
@@ -898,7 +896,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
898
896
|
await simple_run_in_executor(self._result_persistence_helper.save_function_result_to_mongo, current_function_result_status)
|
|
899
897
|
if self._get_priority_conf(kw, 'do_task_filtering'):
|
|
900
898
|
# self._redis_filter.add_a_value(function_only_params) # 函数执行成功后,添加函数的参数排序后的键值对字符串到set中。
|
|
901
|
-
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'))
|
|
902
900
|
if current_function_result_status.success is False and current_retry_times == max_retry_times:
|
|
903
901
|
log_msg = f'函数 {self.consuming_function.__name__} 达到最大重试次数 {self._get_priority_conf(kw, "max_retry_times")} 后,仍然失败, 入参是 {function_only_params} '
|
|
904
902
|
if self.consumer_params.is_push_to_dlx_queue_when_retry_max_times:
|
|
@@ -923,12 +921,12 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
923
921
|
async with self._async_lock_for_count_execute_task_times_every_unit_time:
|
|
924
922
|
self.metric_calculation.cal(t_start_run_fun, current_function_result_status)
|
|
925
923
|
|
|
926
|
-
self._frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
927
|
-
await self._aio_frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
928
|
-
self.user_custom_record_process_info_func(current_function_result_status,) # 两种方式都可以自定义,记录结果.建议使用文档4.21.b的方式继承来重写
|
|
929
|
-
await self.aio_user_custom_record_process_info_func(current_function_result_status,)
|
|
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, )
|
|
930
928
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
931
|
-
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, )
|
|
932
930
|
|
|
933
931
|
except BaseException as e:
|
|
934
932
|
log_msg = f' error 严重错误 {type(e)} {e} '
|
|
@@ -944,17 +942,17 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
944
942
|
"""虽然和上面有点大面积重复相似,这个是为了asyncio模式的,asyncio模式真的和普通同步模式的代码思维和形式区别太大,
|
|
945
943
|
框架实现兼容async的消费函数很麻烦复杂,连并发池都要单独写"""
|
|
946
944
|
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
947
|
-
|
|
945
|
+
|
|
948
946
|
# noinspection PyBroadException
|
|
949
947
|
t_start = time.time()
|
|
950
948
|
fct = funboost_current_task()
|
|
951
949
|
fct_context = FctContext(function_params=function_only_params,
|
|
952
950
|
full_msg=kw['body'],
|
|
953
951
|
function_result_status=function_result_status,
|
|
954
|
-
logger=self.logger,queue_name=self.queue_name,)
|
|
952
|
+
logger=self.logger, queue_name=self.queue_name, )
|
|
955
953
|
fct.set_fct_context(fct_context)
|
|
956
954
|
try:
|
|
957
|
-
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']))
|
|
958
956
|
if not asyncio.iscoroutine(corotinue_obj):
|
|
959
957
|
log_msg = f'''当前设置的并发模式为 async 并发模式,但消费函数不是异步协程函数,请不要把消费函数 {self.consuming_function.__name__} 的 concurrent_mode 设置错误'''
|
|
960
958
|
# self.logger.critical(msg=f'{log_msg} \n')
|
|
@@ -1058,11 +1056,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
1058
1056
|
|
|
1059
1057
|
def pause_consume(self):
|
|
1060
1058
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动停止消费,此功能需要配置好redis"""
|
|
1061
|
-
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')
|
|
1062
1060
|
|
|
1063
1061
|
def continue_consume(self):
|
|
1064
1062
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动继续消费,此功能需要配置好redis"""
|
|
1065
|
-
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')
|
|
1066
1064
|
|
|
1067
1065
|
@decorators.FunctionResultCacher.cached_function_result_for_a_time(120)
|
|
1068
1066
|
def _judge_is_daylight(self):
|
|
@@ -1164,8 +1162,8 @@ class ConcurrentModeDispatcher(FunboostFileLoggerMixin):
|
|
|
1164
1162
|
if self._concurrent_mode == ConcurrentModeEnum.ASYNC:
|
|
1165
1163
|
self.consumer._concurrent_pool = self.consumer.consumer_params.specify_concurrent_pool or pool_type(
|
|
1166
1164
|
self.consumer.consumer_params.concurrent_num,
|
|
1167
|
-
|
|
1168
|
-
|
|
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)
|
|
1169
1167
|
else:
|
|
1170
1168
|
# print(pool_type)
|
|
1171
1169
|
self.consumer._concurrent_pool = self.consumer.consumer_params.specify_concurrent_pool or pool_type(self.consumer.consumer_params.concurrent_num)
|
|
@@ -1212,14 +1210,14 @@ def wait_for_possible_has_finish_all_tasks_by_conusmer_list(consumer_list: typin
|
|
|
1212
1210
|
|
|
1213
1211
|
|
|
1214
1212
|
class MetricCalculation:
|
|
1215
|
-
UNIT_TIME_FOR_COUNT = 10
|
|
1213
|
+
UNIT_TIME_FOR_COUNT = 10 # 这个不要随意改,需要其他地方配合,每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
1216
1214
|
|
|
1217
|
-
def __init__(self,conusmer:AbstractConsumer) -> None:
|
|
1215
|
+
def __init__(self, conusmer: AbstractConsumer) -> None:
|
|
1218
1216
|
self.consumer = conusmer
|
|
1219
1217
|
|
|
1220
1218
|
self.unit_time_for_count = self.UNIT_TIME_FOR_COUNT #
|
|
1221
1219
|
self.execute_task_times_every_unit_time_temp = 0 # 每单位时间执行了多少次任务。
|
|
1222
|
-
self.execute_task_times_every_unit_time_temp_fail =0 # 每单位时间执行了多少次任务失败。
|
|
1220
|
+
self.execute_task_times_every_unit_time_temp_fail = 0 # 每单位时间执行了多少次任务失败。
|
|
1223
1221
|
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1224
1222
|
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1225
1223
|
self.last_execute_task_time = time.time() # 最近一次执行任务的时间。
|
|
@@ -1233,22 +1231,22 @@ class MetricCalculation:
|
|
|
1233
1231
|
self.last_timestamp_when_has_task_in_queue = 0
|
|
1234
1232
|
self.last_timestamp_print_msg_num = 0
|
|
1235
1233
|
|
|
1236
|
-
self.total_consume_count_from_start =0
|
|
1237
|
-
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
|
|
1238
1236
|
self.total_cost_time_from_start = 0 # 函数运行累计花费时间
|
|
1239
1237
|
self.last_x_s_total_cost_time = None
|
|
1240
1238
|
|
|
1241
|
-
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):
|
|
1242
1240
|
self.last_execute_task_time = time.time()
|
|
1243
1241
|
current_msg_cost_time = time.time() - t_start_run_fun
|
|
1244
1242
|
self.execute_task_times_every_unit_time_temp += 1
|
|
1245
|
-
self.total_consume_count_from_start
|
|
1243
|
+
self.total_consume_count_from_start += 1
|
|
1246
1244
|
self.total_cost_time_from_start += current_msg_cost_time
|
|
1247
1245
|
if current_function_result_status.success is False:
|
|
1248
1246
|
self.execute_task_times_every_unit_time_temp_fail += 1
|
|
1249
|
-
self.total_consume_count_from_start_fail +=1
|
|
1247
|
+
self.total_consume_count_from_start_fail += 1
|
|
1250
1248
|
self.consuming_function_cost_time_total_every_unit_time_tmp += current_msg_cost_time
|
|
1251
|
-
|
|
1249
|
+
|
|
1252
1250
|
if time.time() - self.current_time_for_execute_task_times_every_unit_time > self.unit_time_for_count:
|
|
1253
1251
|
self.last_x_s_execute_count = self.execute_task_times_every_unit_time_temp
|
|
1254
1252
|
self.last_x_s_execute_count_fail = self.execute_task_times_every_unit_time_temp_fail
|
|
@@ -1267,30 +1265,30 @@ class MetricCalculation:
|
|
|
1267
1265
|
self.consumer.logger.info(msg)
|
|
1268
1266
|
self.last_show_remaining_execution_time = time.time()
|
|
1269
1267
|
if self.consumer.consumer_params.is_send_consumer_hearbeat_to_redis is True:
|
|
1270
|
-
RedisMixin().redis_db_frame.hincrby(RedisKeys.FUNBOOST_QUEUE__RUN_COUNT_MAP,self.consumer.queue_name,self.execute_task_times_every_unit_time_temp)
|
|
1271
|
-
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)
|
|
1272
1270
|
|
|
1273
1271
|
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1274
1272
|
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1275
1273
|
self.execute_task_times_every_unit_time_temp = 0
|
|
1276
1274
|
self.execute_task_times_every_unit_time_temp_fail = 0
|
|
1277
1275
|
|
|
1278
|
-
def get_report_hearbeat_info(self) ->dict:
|
|
1276
|
+
def get_report_hearbeat_info(self) -> dict:
|
|
1279
1277
|
return {
|
|
1280
|
-
'unit_time_for_count':self.unit_time_for_count,
|
|
1281
|
-
'last_x_s_execute_count':self.last_x_s_execute_count,
|
|
1282
|
-
'last_x_s_execute_count_fail':self.last_x_s_execute_count_fail,
|
|
1283
|
-
'last_execute_task_time':self.last_execute_task_time,
|
|
1284
|
-
'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,
|
|
1285
1283
|
# 'last_show_remaining_execution_time':self.last_show_remaining_execution_time,
|
|
1286
|
-
'msg_num_in_broker':self.msg_num_in_broker,
|
|
1287
|
-
'current_time_for_execute_task_times_every_unit_time':self.current_time_for_execute_task_times_every_unit_time,
|
|
1288
|
-
'last_timestamp_when_has_task_in_queue':self.last_timestamp_when_has_task_in_queue,
|
|
1289
|
-
'total_consume_count_from_start':self.total_consume_count_from_start,
|
|
1290
|
-
'total_consume_count_from_start_fail':self.total_consume_count_from_start_fail,
|
|
1291
|
-
'total_cost_time_from_start':self.total_cost_time_from_start,
|
|
1292
|
-
'last_x_s_total_cost_time':self.last_x_s_total_cost_time,
|
|
1293
|
-
'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,
|
|
1294
1292
|
}
|
|
1295
1293
|
|
|
1296
1294
|
|
|
@@ -1351,11 +1349,10 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1351
1349
|
p.sadd(redis_key, value)
|
|
1352
1350
|
p.execute()
|
|
1353
1351
|
|
|
1354
|
-
|
|
1355
1352
|
def _send_msg_num(self):
|
|
1356
|
-
dic = {'msg_num_in_broker':self._consumer.metric_calculation.msg_num_in_broker,
|
|
1357
|
-
'last_get_msg_num_ts':self._consumer.metric_calculation.last_get_msg_num_ts,
|
|
1358
|
-
'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(),
|
|
1359
1356
|
}
|
|
1360
1357
|
self.redis_db_frame.hset(RedisKeys.QUEUE__MSG_COUNT_MAP, self._consumer.queue_name, json.dumps(dic))
|
|
1361
1358
|
|
|
@@ -1391,16 +1388,14 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1391
1388
|
|
|
1392
1389
|
# noinspection PyProtectedMember
|
|
1393
1390
|
def _get_stop_and_pause_flag_from_redis(self):
|
|
1394
|
-
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)
|
|
1395
1392
|
if stop_flag is not None and int(stop_flag) == 1:
|
|
1396
1393
|
self._consumer._stop_flag = 1
|
|
1397
1394
|
else:
|
|
1398
1395
|
self._consumer._stop_flag = 0
|
|
1399
1396
|
|
|
1400
|
-
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)
|
|
1401
1398
|
if pause_flag is not None and int(pause_flag) == 1:
|
|
1402
1399
|
self._consumer._pause_flag.set()
|
|
1403
1400
|
else:
|
|
1404
1401
|
self._consumer._pause_flag.clear()
|
|
1405
|
-
|
|
1406
|
-
|
|
@@ -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
|
# 这就是核心,
|
|
@@ -23,7 +23,7 @@ class GrpcConsumer(AbstractConsumer, ):
|
|
|
23
23
|
"""
|
|
24
24
|
grpc as broker
|
|
25
25
|
"""
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
|
|
28
28
|
def custom_init(self):
|
|
29
29
|
class FunboostGrpcServicer(funboost_grpc_pb2_grpc.FunboostBrokerServiceServicer):
|
|
@@ -12,11 +12,8 @@ class HueyConsumer(AbstractConsumer):
|
|
|
12
12
|
huey作为中间件实现的。
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
retries=0, retry_delay=0, priority=None, context=False,
|
|
18
|
-
name=None, expires=None, **kwargs
|
|
19
|
-
"""
|
|
15
|
+
|
|
16
|
+
|
|
20
17
|
|
|
21
18
|
def custom_init(self):
|
|
22
19
|
# 这就是核心,
|
|
@@ -22,8 +22,6 @@ class KafkaConsumer(AbstractConsumer):
|
|
|
22
22
|
可以让消费函数内部 sleep60秒,突然停止消费代码,使用 kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group funboost 来证实自动确认消费和手动确认消费的区别。
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
BROKER_EXCLUSIVE_CONFIG_DEFAULT = {'group_id': 'funboost_kafka', 'auto_offset_reset': 'earliest','num_partitions':10,'replication_factor':1,}
|
|
26
|
-
# not_all_brokers_general_settings配置 ,支持独立的中间件配置参数是 group_id 和 auto_offset_reset
|
|
27
25
|
"""
|
|
28
26
|
auto_offset_reset 介绍
|
|
29
27
|
auto_offset_reset (str): A policy for resetting offsets on
|
|
@@ -31,7 +31,6 @@ class KafkaConsumerManuallyCommit(AbstractConsumer):
|
|
|
31
31
|
可以让消费函数内部 sleep 60秒,突然停止消费代码,使用 kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group frame_group 来证实自动确认消费和手动确认消费的区别。
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
BROKER_EXCLUSIVE_CONFIG_DEFAULT = {'group_id': 'funboost_kafka', 'auto_offset_reset': 'earliest','num_partitions':10,'replication_factor':1,}
|
|
35
34
|
|
|
36
35
|
def custom_init(self):
|
|
37
36
|
self._lock_for_operate_offset_dict = threading.Lock()
|