funboost 48.7__py3-none-any.whl → 48.9__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.

Files changed (43) hide show
  1. funboost/__init__.py +1 -1
  2. funboost/__main__.py +2 -0
  3. funboost/concurrent_pool/custom_threadpool_executor.py +1 -1
  4. funboost/constant.py +17 -2
  5. funboost/consumers/base_consumer.py +42 -28
  6. funboost/consumers/rabbitmq_amqpstorm_consumer.py +6 -1
  7. funboost/core/active_cousumer_info_getter.py +50 -10
  8. funboost/core/booster.py +2 -1
  9. funboost/core/cli/funboost_fire.py +10 -0
  10. funboost/core/current_task.py +17 -0
  11. funboost/core/func_params_model.py +21 -17
  12. funboost/core/loggers.py +1 -0
  13. funboost/core/msg_result_getter.py +1 -0
  14. funboost/funboost_config_deafult.py +1 -1
  15. funboost/function_result_web/__pycache__/app.cpython-37.pyc +0 -0
  16. funboost/function_result_web/__pycache__/app.cpython-39.pyc +0 -0
  17. funboost/function_result_web/__pycache__/functions.cpython-37.pyc +0 -0
  18. funboost/function_result_web/__pycache__/functions.cpython-39.pyc +0 -0
  19. funboost/function_result_web/app.py +42 -2
  20. funboost/function_result_web/app_debug_start.py +6 -0
  21. funboost/function_result_web/functions.py +66 -3
  22. funboost/function_result_web/static/js/form-memory.js +92 -0
  23. funboost/function_result_web/static/js_cdn/chart.js +20 -0
  24. funboost/function_result_web/static/js_cdn/tabulator-tables@5.5.0/dist/js/tabulator.min.js +1 -1
  25. funboost/function_result_web/templates/about.html +0 -9
  26. funboost/function_result_web/templates/conusme_speed.html +2 -2
  27. funboost/function_result_web/templates/fun_result_table.html +1 -1
  28. funboost/function_result_web/templates/index.html +64 -9
  29. funboost/function_result_web/templates/queue_op.html +419 -28
  30. funboost/function_result_web/templates/rpc_call.html +312 -0
  31. funboost/function_result_web/templates/running_consumer_by_ip.html +2 -2
  32. funboost/function_result_web/templates/running_consumer_by_queue_name.html +2 -2
  33. funboost/publishers/rabbitmq_amqpstorm_publisher.py +1 -1
  34. funboost/utils/ctrl_c_end.py +19 -1
  35. funboost/utils/dependency_packages_in_pythonpath/aioredis/readme.md +6 -0
  36. funboost/utils/dependency_packages_in_pythonpath/readme.md +6 -0
  37. {funboost-48.7.dist-info → funboost-48.9.dist-info}/METADATA +173 -81
  38. {funboost-48.7.dist-info → funboost-48.9.dist-info}/RECORD +42 -39
  39. {funboost-48.7.dist-info → funboost-48.9.dist-info}/WHEEL +1 -1
  40. funboost/function_result_web/templates/index_/321/204/342/225/225/320/235/321/205/320/237/320/277/321/206/320/232/320/250/321/205/320/237/320/260.html +0 -153
  41. {funboost-48.7.dist-info → funboost-48.9.dist-info}/LICENSE +0 -0
  42. {funboost-48.7.dist-info → funboost-48.9.dist-info}/entry_points.txt +0 -0
  43. {funboost-48.7.dist-info → funboost-48.9.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,9 @@ import os
12
12
 
13
13
  import datetime
14
14
  import json
15
+ import traceback
16
+
17
+ from funboost.core.func_params_model import PriorityConsumingControlConfig
15
18
 
16
19
  """
17
20
  pip install Flask flask_bootstrap flask_wtf wtforms flask_login
@@ -26,6 +29,7 @@ from flask_login import login_user, logout_user, login_required, LoginManager, U
26
29
  import nb_log
27
30
  from funboost import nb_print,ActiveCousumerProcessInfoGetter,BoostersManager,PublisherParams,RedisMixin
28
31
  from funboost.function_result_web.functions import get_cols, query_result, get_speed, Statistic
32
+ from funboost.function_result_web import functions as app_functions
29
33
  from funboost.core.active_cousumer_info_getter import QueueConusmerParamsGetter
30
34
  from funboost.constant import RedisKeys
31
35
 
@@ -119,7 +123,8 @@ def logout():
119
123
  @app.route('/')
120
124
  @login_required
121
125
  def index():
122
- return render_template('index.html')
126
+ page = request.args.get('page')
127
+ return render_template('index.html', page=page)
123
128
 
124
129
 
125
130
  @app.route('/query_cols')
@@ -238,6 +243,39 @@ def resume_consume(queue_name):
238
243
  RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, queue_name,'0')
239
244
  return jsonify({'success':True})
240
245
 
246
+ @app.route('/queue/get_msg_num',methods=['GET'])
247
+ def get_msg_num():
248
+ return jsonify(QueueConusmerParamsGetter().get_msg_num(ignore_report_ts=True))
249
+
250
+ @app.route('/rpc/rpc_call',methods=['POST'])
251
+ def rpc_call():
252
+ """
253
+ class MsgItem(BaseModel):
254
+ queue_name: str # 队列名
255
+ msg_body: dict # 消息体,就是boost函数的入参字典,例如 {"x":1,"y":2}
256
+ need_result: bool = False # 发布消息后,是否需要返回结果
257
+ timeout: int = 60 # 等待结果返回的最大等待时间.
258
+
259
+
260
+ class PublishResponse(BaseModel):
261
+ succ: bool
262
+ msg: str
263
+ status_and_result: typing.Optional[dict] = None # 消费函数的消费状态和结果.
264
+ task_id:str
265
+ """
266
+
267
+ msg_item = request.get_json()
268
+ return jsonify(app_functions.rpc_call(**msg_item))
269
+
270
+ @app.route('/rpc/get_result_by_task_id',methods=['GET'])
271
+ def get_result_by_task_id():
272
+ res = app_functions.get_result_by_task_id(task_id=request.args.get('task_id'),
273
+ timeout=request.args.get('timeout') or 60)
274
+ if res['status_and_result'] is None:
275
+ return jsonify({'succ':False,'msg':'task_id不存在或者超时或者结果已经过期'})
276
+ return jsonify(res)
277
+
278
+
241
279
  def start_funboost_web_manager(host='0.0.0.0', port=27018,block=False):
242
280
  print('start_funboost_web_manager , sys.path :', sys.path)
243
281
  def _start_funboost_web_manager():
@@ -246,7 +284,9 @@ def start_funboost_web_manager(host='0.0.0.0', port=27018,block=False):
246
284
  _start_funboost_web_manager()
247
285
  else:
248
286
  threading.Thread(target=_start_funboost_web_manager).start()
249
-
287
+
288
+
289
+
250
290
  if __name__ == '__main__':
251
291
  # app.jinja_env.auto_reload = True
252
292
  # with app.test_request_context():
@@ -0,0 +1,6 @@
1
+ from funboost.function_result_web.app import app
2
+
3
+
4
+ if __name__ == '__main__':
5
+ app.run(debug=True, threaded=True, host='0.0.0.0', port=27019)
6
+
@@ -6,9 +6,16 @@ import json
6
6
  from pprint import pprint
7
7
  import time
8
8
  import copy
9
+ import traceback
9
10
  from funboost import nb_print
11
+ from funboost.constant import RedisKeys
12
+ from funboost.core.booster import BoostersManager
13
+ from funboost.core.func_params_model import PriorityConsumingControlConfig, PublisherParams
14
+ from funboost.core.msg_result_getter import AsyncResult
15
+ from funboost.core.serialization import Serialization
10
16
  from funboost.utils import time_util, decorators, LoggerMixin
11
17
  from funboost.utils.mongo_util import MongoMixin
18
+ from funboost.utils.redis_manager import RedisMixin
12
19
 
13
20
  # from test_frame.my_patch_frame_config import do_patch_frame_config
14
21
  #
@@ -144,6 +151,55 @@ class Statistic(LoggerMixin):
144
151
  t2.strftime('%Y-%m-%d %H:%M:%S'))
145
152
  self.result['recent_60_seconds']['count_arr'].append(count)
146
153
 
154
+ def rpc_call(queue_name, msg_body, need_result, timeout):
155
+
156
+ status_and_result = None
157
+ task_id = None
158
+ try:
159
+ boost_params_json = RedisMixin().redis_db_frame.hget(RedisKeys.FUNBOOST_QUEUE__CONSUMER_PARAMS,queue_name)
160
+ boost_params_dict = Serialization.to_dict(boost_params_json)
161
+ broker_kind = boost_params_dict['broker_kind']
162
+ publisher = BoostersManager.get_cross_project_publisher(PublisherParams(queue_name=queue_name,
163
+ broker_kind=broker_kind,
164
+ publish_msg_log_use_full_msg=True))
165
+
166
+ if need_result:
167
+ # if booster.boost_params.is_using_rpc_mode is False:
168
+ # raise ValueError(f' need_result 为true,{booster.queue_name} 队列消费者 需要@boost设置支持rpc模式')
169
+
170
+ async_result: AsyncResult = publisher.publish(msg_body,priority_control_config=PriorityConsumingControlConfig(is_using_rpc_mode=True))
171
+ async_result.set_timeout(timeout)
172
+ status_and_result = async_result.status_and_result
173
+ # print(status_and_result)
174
+ task_id = async_result.task_id
175
+ else:
176
+ async_result =publisher.publish(msg_body)
177
+ task_id = async_result.task_id
178
+ if status_and_result['success'] is False:
179
+ return dict(succ=False, msg=f'{queue_name} 队列,消息发布成功,但是函数执行失败',
180
+ status_and_result=status_and_result,task_id=task_id)
181
+ return dict(succ=True, msg=f'{queue_name} 队列,消息发布成功',
182
+ status_and_result=status_and_result,task_id=task_id)
183
+ except Exception as e:
184
+ return dict(succ=False, msg=f'{queue_name} 队列,消息发布失败 {type(e)} {e} {traceback.format_exc()}',
185
+ status_and_result=status_and_result,task_id=task_id)
186
+
187
+
188
+ def get_result_by_task_id(task_id,timeout):
189
+ async_result = AsyncResult(task_id)
190
+ async_result.set_timeout(timeout)
191
+ status_and_result = async_result.status_and_result
192
+ if status_and_result is None:
193
+ return dict(succ=False, msg=f'{task_id} 不存在 或 超时 或 结果已过期',
194
+ status_and_result=status_and_result,task_id=task_id)
195
+ if status_and_result['success'] is False:
196
+ return dict(succ=False, msg=f'{task_id} 执行失败',
197
+ status_and_result=status_and_result,task_id=task_id)
198
+ return dict(succ=True, msg=f'task_id:{task_id} 获取结果成功',
199
+ status_and_result=status_and_result,task_id=task_id)
200
+
201
+
202
+
147
203
 
148
204
  if __name__ == '__main__':
149
205
  # print(get_cols('4'))
@@ -152,6 +208,13 @@ if __name__ == '__main__':
152
208
  # nb_print(get_speed_last_minute('queue_test54'))
153
209
 
154
210
  # nb_print(get_speed('queue_test56', '2019-09-18 16:03:29', '2019-09-23 16:03:29'))
155
- stat = Statistic('queue_test_f01t')
156
- stat.build_result()
157
- nb_print(stat.result)
211
+ # stat = Statistic('queue_test_f01t')
212
+ # stat.build_result()
213
+ # nb_print(stat.result)
214
+
215
+ # res = rpc_call('queue_test_g02t',{'x':1,'y':2},True,60)
216
+
217
+ res = get_result_by_task_id('3232',60)
218
+ print(res)
219
+
220
+
@@ -0,0 +1,92 @@
1
+ // 表单记忆功能 - 保存和恢复iframe内的表单值
2
+ (function() {
3
+ // 简化版 - 只保存基本输入值
4
+ function saveFormInputs() {
5
+ const iframe = document.getElementById('content');
6
+ if (!iframe || !iframe.contentWindow) return;
7
+
8
+ const pageId = iframe.src.split('/').pop().replace('.html', '');
9
+
10
+ try {
11
+ const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
12
+ const formData = {};
13
+
14
+ // 保存所有输入元素值
15
+ const inputs = iframeDoc.querySelectorAll('input, textarea, select');
16
+ inputs.forEach(input => {
17
+ const inputId = input.id || input.name || input.getAttribute('placeholder');
18
+ if (inputId) {
19
+ formData[inputId] = input.value;
20
+ }
21
+ });
22
+
23
+ // 特殊处理下拉框的选中文本
24
+ const selects = iframeDoc.querySelectorAll('select');
25
+ selects.forEach(select => {
26
+ const inputId = select.id || select.name;
27
+ if (inputId && select.selectedIndex >= 0 && select.options[select.selectedIndex]) {
28
+ formData[`${inputId}_text`] = select.options[select.selectedIndex].text;
29
+ }
30
+ });
31
+
32
+ localStorage.setItem(`funboost_form_${pageId}`, JSON.stringify(formData));
33
+ } catch (e) {
34
+ console.error("保存表单数据失败:", e);
35
+ }
36
+ }
37
+
38
+ // 简化版 - 只恢复基本输入值
39
+ function restoreFormInputs() {
40
+ setTimeout(() => {
41
+ const iframe = document.getElementById('content');
42
+ if (!iframe || !iframe.contentWindow) return;
43
+
44
+ const pageId = iframe.src.split('/').pop().replace('.html', '');
45
+ const savedData = localStorage.getItem(`funboost_form_${pageId}`);
46
+
47
+ if (savedData) {
48
+ try {
49
+ const formData = JSON.parse(savedData);
50
+ const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
51
+
52
+ // 恢复所有基本输入元素的值
53
+ Object.keys(formData).forEach(inputId => {
54
+ if (inputId.endsWith('_text')) return;
55
+
56
+ const input = iframeDoc.getElementById(inputId) ||
57
+ iframeDoc.querySelector(`[name="${inputId}"]`) ||
58
+ iframeDoc.querySelector(`[placeholder="${inputId}"]`);
59
+
60
+ if (input) {
61
+ input.value = formData[inputId];
62
+
63
+ // 触发change事件
64
+ const event = new Event('change', { bubbles: true });
65
+ input.dispatchEvent(event);
66
+ }
67
+ });
68
+ } catch (e) {
69
+ console.error("恢复表单数据失败:", e);
70
+ }
71
+ }
72
+ }, 500);
73
+ }
74
+
75
+ // 当DOM加载完成时初始化事件监听
76
+ document.addEventListener('DOMContentLoaded', function() {
77
+ // 监听iframe加载完成事件
78
+ const contentFrame = document.getElementById('content');
79
+ if (contentFrame) {
80
+ contentFrame.addEventListener('load', restoreFormInputs);
81
+ }
82
+
83
+ // 在页面切换前保存
84
+ const navLinks = document.querySelectorAll('.sidebar .nav-link');
85
+ navLinks.forEach(link => {
86
+ link.addEventListener('click', saveFormInputs);
87
+ });
88
+
89
+ // 页面离开前保存
90
+ window.addEventListener('beforeunload', saveFormInputs);
91
+ });
92
+ })();