funboost 50.0__py3-none-any.whl → 50.2__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/consumers/base_consumer.py +42 -14
- funboost/consumers/faststream_consumer.py +1 -0
- funboost/core/active_cousumer_info_getter.py +26 -4
- funboost/core/funboost_time.py +41 -1
- funboost/core/function_result_status_saver.py +4 -4
- funboost/core/helper_funs.py +16 -3
- funboost/function_result_web/__pycache__/app.cpython-39.pyc +0 -0
- funboost/function_result_web/app.py +20 -1
- funboost/function_result_web/templates/queue_op.html +251 -43
- funboost-50.2.dist-info/METADATA +785 -0
- {funboost-50.0.dist-info → funboost-50.2.dist-info}/RECORD +16 -16
- {funboost-50.0.dist-info → funboost-50.2.dist-info}/WHEEL +1 -1
- funboost-50.0.dist-info/METADATA +0 -809
- {funboost-50.0.dist-info → funboost-50.2.dist-info}/LICENSE +0 -0
- {funboost-50.0.dist-info → funboost-50.2.dist-info}/entry_points.txt +0 -0
- {funboost-50.0.dist-info → funboost-50.2.dist-info}/top_level.txt +0 -0
funboost/__init__.py
CHANGED
|
@@ -168,8 +168,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
168
168
|
# if self.consumer_params.concurrent_mode == ConcurrentModeEnum.ASYNC and self.consumer_params.specify_async_loop is None:
|
|
169
169
|
# self.consumer_params.specify_async_loop= get_or_create_event_loop()
|
|
170
170
|
self._lock_for_count_execute_task_times_every_unit_time = Lock()
|
|
171
|
-
|
|
172
|
-
self._async_lock_for_count_execute_task_times_every_unit_time = asyncio.Lock()
|
|
171
|
+
|
|
173
172
|
# self._unit_time_for_count = 10 # 每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
174
173
|
# self._execute_task_times_every_unit_time = 0 # 每单位时间执行了多少次任务。
|
|
175
174
|
# self._execute_task_times_every_unit_time_fail =0 # 每单位时间执行了多少次任务失败。
|
|
@@ -491,7 +490,6 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
491
490
|
return msg
|
|
492
491
|
|
|
493
492
|
def _submit_task(self, kw):
|
|
494
|
-
|
|
495
493
|
kw['body'] = self._convert_msg_before_run(kw['body'])
|
|
496
494
|
self._print_message_get_from_broker(kw['body'])
|
|
497
495
|
if self._judge_is_daylight():
|
|
@@ -499,6 +497,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
499
497
|
time.sleep(self.time_interval_for_check_do_not_run_time)
|
|
500
498
|
return
|
|
501
499
|
function_only_params = delete_keys_and_return_new_dict(kw['body'], )
|
|
500
|
+
kw['function_only_params'] = function_only_params
|
|
502
501
|
if self._get_priority_conf(kw, 'do_task_filtering') and self._redis_filter.check_value_exists(
|
|
503
502
|
function_only_params,self._get_priority_conf(kw, 'filter_str')): # 对函数的参数进行检查,过滤已经执行过并且成功的任务。
|
|
504
503
|
self.logger.warning(f'redis的 [{self._redis_filter_key_name}] 键 中 过滤任务 {kw["body"]}')
|
|
@@ -688,7 +687,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
688
687
|
max_retry_times = self._get_priority_conf(kw, 'max_retry_times')
|
|
689
688
|
current_function_result_status = FunctionResultStatus(self.queue_name, self.consuming_function.__name__, kw['body'], )
|
|
690
689
|
current_retry_times = 0
|
|
691
|
-
function_only_params =
|
|
690
|
+
function_only_params = kw['function_only_params']
|
|
692
691
|
for current_retry_times in range(max_retry_times + 1):
|
|
693
692
|
current_function_result_status.run_times = current_retry_times + 1
|
|
694
693
|
current_function_result_status.run_status = RunStatus.running
|
|
@@ -747,10 +746,10 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
747
746
|
# noinspection PyProtectedMember
|
|
748
747
|
def _run_consuming_function_with_confirm_and_retry(self, kw: dict, current_retry_times,
|
|
749
748
|
function_result_status: FunctionResultStatus, ):
|
|
750
|
-
function_only_params =
|
|
749
|
+
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
751
750
|
task_id = kw['body']['extra']['task_id']
|
|
752
751
|
t_start = time.time()
|
|
753
|
-
|
|
752
|
+
|
|
754
753
|
fct = funboost_current_task()
|
|
755
754
|
fct_context = FctContext(function_params=function_only_params,
|
|
756
755
|
full_msg=kw['body'],
|
|
@@ -837,17 +836,47 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
837
836
|
|
|
838
837
|
function_result_status.result = FunctionResultStatus.FUNC_RUN_ERROR
|
|
839
838
|
return function_result_status
|
|
840
|
-
|
|
839
|
+
|
|
840
|
+
def _gen_asyncio_objects(self):
|
|
841
|
+
if getattr(self, '_async_lock_for_count_execute_task_times_every_unit_time', None) is None:
|
|
842
|
+
self._async_lock_for_count_execute_task_times_every_unit_time = asyncio.Lock()
|
|
843
|
+
|
|
841
844
|
# noinspection PyProtectedMember
|
|
842
845
|
async def _async_run(self, kw: dict, ):
|
|
843
|
-
|
|
844
|
-
|
|
846
|
+
"""
|
|
847
|
+
虽然 async def _async_run 和上面的 def _run 有点大面积结构重复相似,这个是为了asyncio模式的,
|
|
848
|
+
asyncio模式真的和普通同步模式的代码思维和形式区别太大,
|
|
849
|
+
框架实现兼容async的消费函数很麻烦复杂,连并发池都要单独写
|
|
850
|
+
|
|
851
|
+
_run 和 _async_run 无法合并成一个方法:
|
|
852
|
+
因为在一个函数体内部,您无法根据条件来决定是否使用 await。
|
|
853
|
+
|
|
854
|
+
Python 语法不允许这样做:
|
|
855
|
+
# 伪代码,这是无效的
|
|
856
|
+
def _unified_run(self, kw, is_async):
|
|
857
|
+
# ...
|
|
858
|
+
if is_async:
|
|
859
|
+
await asyncio.sleep(1) # 'await' outside async function 经典报错
|
|
860
|
+
else:
|
|
861
|
+
time.sleep(1)
|
|
862
|
+
|
|
863
|
+
不能在同步函数里面去写 await,只要一个函数里出现了 await,这个函数就必须被声明为 async def
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
funboost 这个代价算小了,为了支持异步的全流程生态包括发布/消费/获取rpc结果,对asyncio的累计专门投入代码不到500行.
|
|
868
|
+
如果是celery 改造适配asyncio,起码要增加10倍以上的代码量,改5000行代码都搞不定支持真asyncio并发.
|
|
869
|
+
我说的是支持兼容真asyncio并发,而不是每个线程内部搞个临时loop,然后临时loop.run_until_complete(用户async函数) 这种伪asyncio并发,
|
|
870
|
+
真asyncio并发,是单个loop里面运行无数协程,
|
|
871
|
+
伪asyncio并发是在每个线程启动一个临时的loop,每个loop仅仅运行一个协程,然后等待这个协程结束,这完全违背了 asyncio 的核心初心理念,这种比多线程性能本身还差.
|
|
872
|
+
"""
|
|
845
873
|
try:
|
|
874
|
+
self._gen_asyncio_objects()
|
|
846
875
|
t_start_run_fun = time.time()
|
|
847
876
|
max_retry_times = self._get_priority_conf(kw, 'max_retry_times')
|
|
848
877
|
current_function_result_status = FunctionResultStatus(self.queue_name, self.consuming_function.__name__, kw['body'], )
|
|
849
878
|
current_retry_times = 0
|
|
850
|
-
function_only_params =
|
|
879
|
+
function_only_params = kw['function_only_params']
|
|
851
880
|
for current_retry_times in range(max_retry_times + 1):
|
|
852
881
|
current_function_result_status.run_times = current_retry_times + 1
|
|
853
882
|
current_function_result_status.run_status = RunStatus.running
|
|
@@ -888,11 +917,10 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
888
917
|
|
|
889
918
|
if (current_function_result_status.success is False and current_retry_times == max_retry_times) or current_function_result_status.success is True:
|
|
890
919
|
await simple_run_in_executor(push_result)
|
|
891
|
-
|
|
892
920
|
async with self._async_lock_for_count_execute_task_times_every_unit_time:
|
|
893
921
|
self.metric_calculation.cal(t_start_run_fun, current_function_result_status)
|
|
894
922
|
|
|
895
|
-
self._frame_custom_record_process_info_func(current_function_result_status)
|
|
923
|
+
self._frame_custom_record_process_info_func(current_function_result_status,kw)
|
|
896
924
|
self.user_custom_record_process_info_func(current_function_result_status,) # 两种方式都可以自定义,记录结果.建议使用文档4.21.b的方式继承来重写
|
|
897
925
|
await self.aio_user_custom_record_process_info_func(current_function_result_status,)
|
|
898
926
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
@@ -911,8 +939,8 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
911
939
|
function_result_status: FunctionResultStatus, ):
|
|
912
940
|
"""虽然和上面有点大面积重复相似,这个是为了asyncio模式的,asyncio模式真的和普通同步模式的代码思维和形式区别太大,
|
|
913
941
|
框架实现兼容async的消费函数很麻烦复杂,连并发池都要单独写"""
|
|
914
|
-
function_only_params =
|
|
915
|
-
|
|
942
|
+
function_only_params = kw['function_only_params'] if self._do_not_delete_extra_from_msg is False else kw['body']
|
|
943
|
+
|
|
916
944
|
# noinspection PyBroadException
|
|
917
945
|
t_start = time.time()
|
|
918
946
|
fct = funboost_current_task()
|
|
@@ -9,6 +9,7 @@ from faststream import FastStream,Context
|
|
|
9
9
|
from faststream.annotations import Logger
|
|
10
10
|
|
|
11
11
|
from funboost.concurrent_pool.async_helper import simple_run_in_executor
|
|
12
|
+
from funboost.core.serialization import Serialization
|
|
12
13
|
from funboost.core.helper_funs import delete_keys_and_return_new_dict
|
|
13
14
|
|
|
14
15
|
|
|
@@ -205,12 +205,13 @@ class QueueConusmerParamsGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
|
205
205
|
def _inner():
|
|
206
206
|
while True:
|
|
207
207
|
t_start = time.time()
|
|
208
|
-
#
|
|
208
|
+
# 这个函数确保只有一个地方在上报数据,避免重复采集上报
|
|
209
209
|
report_ts = self.timestamp()
|
|
210
210
|
redis_report_uuid_ts_str = self.redis_db_frame.get(RedisKeys.FUNBOOST_LAST_GET_QUEUE_PARAMS_AND_ACTIVE_CONSUMERS_AND_REPORT__UUID_TS, )
|
|
211
211
|
if redis_report_uuid_ts_str:
|
|
212
212
|
redis_report_uuid_ts = Serialization.to_dict(redis_report_uuid_ts_str)
|
|
213
213
|
if redis_report_uuid_ts['report_uuid'] != report_uuid and redis_report_uuid_ts['report_ts'] > report_ts - time_interval - 10 :
|
|
214
|
+
time.sleep(5) # 防止cpu空转
|
|
214
215
|
continue
|
|
215
216
|
self.redis_db_frame.set(RedisKeys.FUNBOOST_LAST_GET_QUEUE_PARAMS_AND_ACTIVE_CONSUMERS_AND_REPORT__UUID_TS,
|
|
216
217
|
Serialization.to_json_str({'report_uuid':report_uuid, 'report_ts':report_ts}))
|
|
@@ -229,17 +230,38 @@ class QueueConusmerParamsGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
|
229
230
|
RedisKeys.gen_funboost_queue_time_series_data_key_by_queue_name(queue),
|
|
230
231
|
0, report_ts - 86400
|
|
231
232
|
)
|
|
232
|
-
self.logger.info(f'
|
|
233
|
+
self.logger.info(f'采集上报时序数据耗时 {time.time() - t_start} 秒')
|
|
233
234
|
|
|
234
235
|
time.sleep(time_interval)
|
|
235
236
|
threading.Thread(target=_inner, daemon=daemon).start()
|
|
236
237
|
|
|
237
|
-
def get_time_series_data_by_queue_name(self,queue_name,start_ts=None,end_ts=None):
|
|
238
|
+
def get_time_series_data_by_queue_name(self,queue_name,start_ts=None,end_ts=None,curve_samples_count=None):
|
|
238
239
|
res = self.redis_db_frame.zrangebyscore(
|
|
239
240
|
RedisKeys.gen_funboost_queue_time_series_data_key_by_queue_name(queue_name),
|
|
240
241
|
max(float(start_ts or 0),self.timestamp() - 86400) ,float(end_ts or -1),withscores=True)
|
|
241
242
|
# print(res)
|
|
242
|
-
|
|
243
|
+
series_data_all= [{'report_data':Serialization.to_dict(item[0]),'report_ts':item[1]} for item in res]
|
|
244
|
+
if curve_samples_count is None:
|
|
245
|
+
return series_data_all
|
|
246
|
+
|
|
247
|
+
# 曲线采样数量
|
|
248
|
+
total_count = len(series_data_all)
|
|
249
|
+
if total_count <= curve_samples_count:
|
|
250
|
+
# 如果原始数据量小于等于需要的样本数,直接返回全部数据
|
|
251
|
+
return series_data_all
|
|
252
|
+
|
|
253
|
+
# 计算采样步长
|
|
254
|
+
step = total_count / curve_samples_count
|
|
255
|
+
sampled_data = []
|
|
256
|
+
|
|
257
|
+
# 按照步长进行采样
|
|
258
|
+
for i in range(curve_samples_count):
|
|
259
|
+
index = int(i * step)
|
|
260
|
+
if index < total_count:
|
|
261
|
+
sampled_data.append(series_data_all[index])
|
|
262
|
+
|
|
263
|
+
return sampled_data
|
|
264
|
+
|
|
243
265
|
|
|
244
266
|
if __name__ == '__main__':
|
|
245
267
|
# print(Serialization.to_json_str(QueueConusmerParamsGetter().get_queue_params_and_active_consumers()))
|
funboost/core/funboost_time.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pytz
|
|
2
2
|
import time
|
|
3
|
-
|
|
3
|
+
import sys
|
|
4
4
|
import datetime
|
|
5
5
|
|
|
6
6
|
import typing
|
|
@@ -28,6 +28,46 @@ class FunboostTime(NbTime):
|
|
|
28
28
|
return t_str
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# 缓存时区对象,提升性能(避免重复解析)
|
|
34
|
+
_tz_cache = {}
|
|
35
|
+
|
|
36
|
+
def get_now_time_str_by_tz(tz_name: str=None) -> str:
|
|
37
|
+
"""
|
|
38
|
+
根据时区名(如 'Asia/Shanghai')返回当前时间字符串,格式:'%Y-%m-%d %H:%M:%S'
|
|
39
|
+
|
|
40
|
+
兼容 Python 3.6+,优先使用 zoneinfo(3.9+),否则尝试 pytz
|
|
41
|
+
|
|
42
|
+
:param tz_name: IANA 时区名称,如 'Asia/Shanghai', 'America/New_York'
|
|
43
|
+
:return: 格式化时间字符串
|
|
44
|
+
"""
|
|
45
|
+
# 检查缓存
|
|
46
|
+
tz_name = tz_name or FunboostCommonConfig.TIMEZONE
|
|
47
|
+
if tz_name not in _tz_cache:
|
|
48
|
+
if sys.version_info >= (3, 9):
|
|
49
|
+
from zoneinfo import ZoneInfo
|
|
50
|
+
_tz_cache[tz_name] = ZoneInfo(tz_name)
|
|
51
|
+
else:
|
|
52
|
+
# Python < 3.9,使用 pytz
|
|
53
|
+
try:
|
|
54
|
+
import pytz
|
|
55
|
+
_tz_cache[tz_name] = pytz.timezone(tz_name)
|
|
56
|
+
except ImportError:
|
|
57
|
+
raise RuntimeError(
|
|
58
|
+
f"Python < 3.9 requires 'pytz' to handle timezones. "
|
|
59
|
+
f"Install it with: pip install pytz"
|
|
60
|
+
) from None
|
|
61
|
+
except pytz.UnknownTimeZoneError:
|
|
62
|
+
raise pytz.UnknownTimeZoneError(tz_name)
|
|
63
|
+
|
|
64
|
+
tz = _tz_cache[tz_name]
|
|
65
|
+
|
|
66
|
+
# 获取当前时间并格式化(注意:datetime.now(tz) 是最高效的方式)
|
|
67
|
+
now = datetime.datetime.now(tz)
|
|
68
|
+
return f'{now.year:04d}-{now.month:02d}-{now.day:02d} {now.hour:02d}:{now.minute:02d}:{now.second:02d}'
|
|
69
|
+
# return now.strftime("%Y-%m-%d %H:%M:%S")
|
|
70
|
+
|
|
31
71
|
if __name__ == '__main__':
|
|
32
72
|
print(FunboostTime().get_str())
|
|
33
73
|
tz=pytz.timezone(FunboostCommonConfig.TIMEZONE)
|
|
@@ -14,7 +14,7 @@ import sys
|
|
|
14
14
|
from pymongo import IndexModel, ReplaceOne
|
|
15
15
|
|
|
16
16
|
from funboost.core.func_params_model import FunctionResultStatusPersistanceConfig
|
|
17
|
-
from funboost.core.helper_funs import get_publish_time, delete_keys_and_return_new_dict
|
|
17
|
+
from funboost.core.helper_funs import get_publish_time, delete_keys_and_return_new_dict, get_publish_time_format
|
|
18
18
|
from funboost.core.serialization import Serialization
|
|
19
19
|
from funboost.utils import time_util, decorators
|
|
20
20
|
from funboost.utils.mongo_util import MongoMixin
|
|
@@ -42,9 +42,9 @@ class FunctionResultStatus():
|
|
|
42
42
|
self.task_id = self.msg_dict.get('extra', {}).get('task_id', '')
|
|
43
43
|
self.process_id = os.getpid()
|
|
44
44
|
self.thread_id = threading.get_ident()
|
|
45
|
-
self.publish_time
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
self.publish_time = get_publish_time(msg_dict)
|
|
46
|
+
self.publish_time_format = get_publish_time_format(msg_dict)
|
|
47
|
+
# print(self.publish_time_format)
|
|
48
48
|
function_params = delete_keys_and_return_new_dict(msg_dict, )
|
|
49
49
|
self.params = function_params
|
|
50
50
|
self.params_str = Serialization.to_json_str(function_params)
|
funboost/core/helper_funs.py
CHANGED
|
@@ -3,7 +3,7 @@ import pytz
|
|
|
3
3
|
import time
|
|
4
4
|
import uuid
|
|
5
5
|
import datetime
|
|
6
|
-
from funboost.core.funboost_time import FunboostTime
|
|
6
|
+
from funboost.core.funboost_time import FunboostTime, get_now_time_str_by_tz
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def get_publish_time(paramsx: dict):
|
|
@@ -14,6 +14,14 @@ def get_publish_time(paramsx: dict):
|
|
|
14
14
|
return paramsx.get('extra', {}).get('publish_time', None)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def get_publish_time_format(paramsx: dict):
|
|
18
|
+
"""
|
|
19
|
+
:param paramsx:
|
|
20
|
+
:return:
|
|
21
|
+
"""
|
|
22
|
+
return paramsx.get('extra', {}).get('publish_time_format', None)
|
|
23
|
+
|
|
24
|
+
|
|
17
25
|
def delete_keys_and_return_new_dict(dictx: dict, keys: list = None):
|
|
18
26
|
dict_new = copy.deepcopy(dictx) # 主要是去掉一级键 publish_time,浅拷贝即可。新的消息已经不是这样了。
|
|
19
27
|
keys = ['publish_time', 'publish_time_format', 'extra'] if keys is None else keys
|
|
@@ -49,13 +57,18 @@ class MsgGenerater:
|
|
|
49
57
|
def generate_publish_time() -> float:
|
|
50
58
|
return round(time.time(),4)
|
|
51
59
|
|
|
60
|
+
# @staticmethod # 性能不好
|
|
61
|
+
# def generate_publish_time_format() -> str:
|
|
62
|
+
# return FunboostTime().get_str()
|
|
63
|
+
|
|
52
64
|
@staticmethod
|
|
53
65
|
def generate_publish_time_format() -> str:
|
|
54
|
-
return
|
|
66
|
+
return get_now_time_str_by_tz()
|
|
55
67
|
|
|
56
68
|
@classmethod
|
|
57
69
|
def generate_pulish_time_and_task_id(cls,queue_name:str,task_id=None):
|
|
58
|
-
extra_params = {'task_id': task_id or cls.generate_task_id(queue_name),
|
|
70
|
+
extra_params = {'task_id': task_id or cls.generate_task_id(queue_name),
|
|
71
|
+
'publish_time': cls.generate_publish_time(),
|
|
59
72
|
'publish_time_format': cls.generate_publish_time_format()}
|
|
60
73
|
return extra_params
|
|
61
74
|
|
|
Binary file
|
|
@@ -271,8 +271,27 @@ def get_time_series_data_by_queue_name(queue_name,):
|
|
|
271
271
|
|
|
272
272
|
返回例如 [{'report_data': {'pause_flag': -1, 'msg_num_in_broker': 936748, 'history_run_count': '150180', 'history_run_fail_count': '46511', 'all_consumers_last_x_s_execute_count': 7, 'all_consumers_last_x_s_execute_count_fail': 0, 'all_consumers_last_x_s_avarage_function_spend_time': 3.441, 'all_consumers_avarage_function_spend_time_from_start': 4.598, 'all_consumers_total_consume_count_from_start': 1296, 'all_consumers_total_consume_count_from_start_fail': 314, 'report_ts': 1749617360.597841}, 'report_ts': 1749617360.597841}, {'report_data': {'pause_flag': -1, 'msg_num_in_broker': 936748, 'history_run_count': '150184', 'history_run_fail_count': '46514', 'all_consumers_last_x_s_execute_count': 7, 'all_consumers_last_x_s_execute_count_fail': 0, 'all_consumers_last_x_s_avarage_function_spend_time': 3.441, 'all_consumers_avarage_function_spend_time_from_start': 4.599, 'all_consumers_total_consume_count_from_start': 1299, 'all_consumers_total_consume_count_from_start_fail': 316, 'report_ts': 1749617370.628166}, 'report_ts': 1749617370.628166}]
|
|
273
273
|
"""
|
|
274
|
+
# 获取前端传递的参数
|
|
275
|
+
start_ts = request.args.get('start_ts')
|
|
276
|
+
end_ts = request.args.get('end_ts')
|
|
277
|
+
curve_samples_count = request.args.get('curve_samples_count')
|
|
278
|
+
|
|
279
|
+
# 如果前端指定了采样点数,使用前端的值
|
|
280
|
+
if curve_samples_count:
|
|
281
|
+
try:
|
|
282
|
+
curve_samples_count = int(curve_samples_count)
|
|
283
|
+
# 验证值是否在允许的范围内
|
|
284
|
+
allowed_values = [60, 120, 180, 360, 720, 1440,8640]
|
|
285
|
+
if curve_samples_count not in allowed_values:
|
|
286
|
+
curve_samples_count = 360 # 默认值
|
|
287
|
+
except (ValueError, TypeError):
|
|
288
|
+
curve_samples_count = 360 # 默认值
|
|
289
|
+
else:
|
|
290
|
+
# 如果前端没有指定,使用默认值
|
|
291
|
+
curve_samples_count = 360
|
|
292
|
+
|
|
274
293
|
return jsonify(QueueConusmerParamsGetter().get_time_series_data_by_queue_name(
|
|
275
|
-
queue_name,
|
|
294
|
+
queue_name, start_ts, end_ts, curve_samples_count))
|
|
276
295
|
|
|
277
296
|
@app.route('/rpc/rpc_call',methods=['POST'])
|
|
278
297
|
def rpc_call():
|