### Basic funboost Framework Initialization Source: https://github.com/ydf0509/funboost/blob/master/README.md This Python code snippet demonstrates the fundamental imports required to start using the funboost framework. It shows how to import `boost`, `BrokerEnum`, and `BoosterParams` for setting up a basic distributed task. ```python import time from funboost import boost, BrokerEnum,BoosterParams ``` -------------------------------- ### Load Queues and Initialize Select2 - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/rpc_call.html This script executes when the document is ready. It makes an AJAX GET request to fetch queue names and their message counts, populates a select dropdown with this data, and initializes the dropdown with the Select2 library for enhanced search functionality. It also adds a change listener to the dropdown. ```javascript $(document).ready(function () { var allQueues = []; // \u5b58\u50a8\u6240\u6709\u961f\u5217\u6570\u636e var currentColName; // \u9875\u9762\u52a0\u8f7d\u5b8c\u6210\u540e\u7acb\u5373\u83b7\u53d6\u6240\u6709\u961f\ ``` -------------------------------- ### Defining Example Person Class (JavaScript) Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/index_backup.html Defines a simple JavaScript class named Person. It has a constructor that takes name and age parameters and stores them as instance properties. It also includes a say method that returns a string describing the person using their name and age. This appears to be an unrelated example. ```JavaScript class Person {//定义了一个名字为Person的类 constructor(name, age) {//constructor是一个构造方法,用来接收参数 this.name = name;//this代表的是实例对象 this.age = age; } say() {//这是一个类的方法,注意千万不要加上function return "我的名字叫" + this.name + "今年" + this.age + "岁了"; } } ``` -------------------------------- ### Defining and Consuming a Basic funboost Task Source: https://github.com/ydf0509/funboost/blob/master/README.md This example demonstrates defining a task `task_fun` using the `@boost` decorator with `BoosterParams` to specify queue name, QPS, and broker type (SQLite). It shows how to publish tasks using `task_fun.push()` and consume them with `task_fun.consume()`. The framework automatically manages concurrency to achieve the specified QPS, even with internal delays, and supports decoupled publishers and consumers. Note: For SQLite on Linux/Mac, ensure `SQLLITE_QUEUES_PATH` has write permissions. ```python @boost(BoosterParams(queue_name="task_queue_name1", qps=5, broker_kind=BrokerEnum.SQLITE_QUEUE)) # \u5165\u53c2\u5305\u62ec20\u79cd\uff0c\u8fd0\u884c\u63a7\u5236\u65b9\u5f0f\u975e\u5e38\u591a\uff0c\u60f3\u5f97\u5230\u7684\u63a7\u5236\u90fd\u4f1a\u6709\u3002 def task_fun(x, y): print(f'{x} + {y} = {x + y}') time.sleep(3) # \u6846\u67b6\u4f1a\u81ea\u52a8\u5e76\u53d1\u7ed5\u5f00\u8fd9\u4e2a\u963b\u585e\uff0c\u65e0\u8bba\u51fd\u6570\u5185\u90e8\u968f\u673a\u8017\u65f6\u591a\u4e45\u90fd\u80fd\u81ea\u52a8\u8c03\u8282\u5e76\u53d1\u8fbe\u5230\u6bcf\u79d2\u8fd0\u884c 5 \u6b21 \u8fd9\u4e2a task_fun \u51fd\u6570\u7684\u76ee\u7684\u3002 if __name__ == "__main__": for i in range(100): task_fun.push(i, y=i * 2) # \u53d1\u5e03\u8005\u53d1\u5e03\u4efb\u52a1 task_fun.consume() # \u6d88\u8d39\u8005\u542f\u52a8\u5faa\u73af\u8c03\u5ea6\u5e76\u53d1\u6d88\u8d39\u4efb\u52a1 ``` -------------------------------- ### Chaining Multiple funboost Tasks with Non-Blocking Consumption Source: https://github.com/ydf0509/funboost/blob/master/README.md This example demonstrates funboost's support for non-blocking startup of multiple function consumers and chaining tasks. It shows how to define custom `BoosterParams` for common settings and how a consumer function (`step1`) can publish new tasks to another queue (`step2`), creating a multi-level task chain. The `consume()` method is non-blocking, allowing multiple consumers to be started sequentially without blocking the main thread. ```python """ \u6b64\u4ee3\u7801 1.\u6f14\u793a\u652f\u6301\u591a\u4e2a\u51fd\u6570\u6d88\u8d39\u961f\u5217\u7684\u65e0\u963b\u585e\u542f\u52a8\uff08consume\u4e0d\u4f1a\u963b\u585e\u4e3b\u7ebf\u7a0b\uff09 2.\u6f14\u793a\u652f\u6301\u5728\u4e00\u4e2a\u6d88\u8d39\u51fd\u6570\u5185\u90e8\u5411\u4efb\u610f\u961f\u5217\u53d1\u5e03\u65b0\u4efb\u52a1\uff0c\u5b9e\u73b0\u591a\u7ea7\u4efb\u52a1\u94fe \u4ee3\u7801\u7ed3\u6784\u6e05\u6670\uff0c\u6269\u5c55\u6027\u6781\u5f3a """ from funboost import boost, BrokerEnum,BoosterParams,ctrl_c_recv,ConcurrentModeEnum import time class MyBoosterParams(BoosterParams): # \u81ea\u5b9a\u4e49\u7684\u53c2\u6570\u7c7b\uff0c\u7ee7\u627fBoosterParams\uff0c\u7528\u4e8e\u51cf\u5c11\u6bcf\u4e2a\u6d88\u8d39\u51fd\u6570\u88c5\u9970\u5668\u7684\u91cd\u590d\u76f8\u540c\u5165\u53c2\u4e2a\u6570 broker_kind: str = BrokerEnum.MEMORY_QUEUE max_retry_times: int = 3 concurrent_mode: str = ConcurrentModeEnum.THREADING @boost(MyBoosterParams(queue_name='s1_queue', qps=1, )) def step1(a:int,b:int): print(f'a={a},b={b}') time.sleep(0.7) for j in range(10): step2.push(c=a+b +j,d=a*b +j,e=a-b +j ) # step1\u6d88\u8d39\u51fd\u6570\u91cc\u9762\uff0c\u4e5f\u53ef\u4ee5\u7ee7\u7eed\u5411\u5176\u4ed6\u4efb\u610f\u961f\u5217\u53d1\u5e03\u6d88\u606f\u3002 return a+b @boost(MyBoosterParams(queue_name='s2_queue', qps=3, )) def step2(c:int,d:int,e:int): time.sleep(3) print(f'c={c},d={d},e={e}') return c* d * e if __name__ == '__main__': for i in range(100): step1.push(i,i*2) # \u5411 step1\u51fd\u6570\u7684\u961f\u5217\u53d1\u9001\u6d88\u606f\u3002 step1.consume() # \u8c03\u7528.consume\u662f\u975e\u963b\u585e\u7684\u542f\u52a8\u6d88\u8d39\uff0c\u662f\u5728\u5355\u72ec\u7684\u5b50\u7ebf\u7a0b\u4e2d\u5faa\u73af\u62c9\u53d6\u6d88\u606f\u7684\u3002 # \u6709\u7684\u4eba\u8fd8\u62c5\u5fc3\u963b\u585e\u800c\u624b\u52a8\u4f7f\u7528 threading.Thread(target=step1.consume).start() \u6765\u542f\u52a8\u6d88\u8d39\uff0c\u8fd9\u662f\u5b8c\u5168\u591a\u6b64\u4e00\u4e3e\u7684\u9519\u8bef\u5199\u6cd5\u3002 step2.consume() # \u6240\u4ee5\u53ef\u4ee5\u8fde\u7eed\u65e0\u963b\u585e\u4e1d\u6ed1\u7684\u542f\u52a8\u591a\u4e2a\u51fd\u6570\u6d88\u8d39\u3002 ctrl_c_recv() ``` -------------------------------- ### Defining Start Auto-Refresh Function (JavaScript) Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/index_backup.html Defines the startRun function. It updates the text and classes of an element with ID autoFresh to indicate that auto-refresh is active (changes text to "自动刷新中", removes "btn-danger", adds "btn-success"). It then starts the autoFreshResult interval using setInterval and sets runStatus to 1. ```JavaScript function startRun() { $("#autoFresh").text("自动刷新中"); $("#autoFresh").removeClass("btn-danger"); $("#autoFresh").addClass("btn-success"); iid = setInterval(autoFreshResult, 5000); runStatus = 1; } ``` -------------------------------- ### Set Default Date Range Inputs - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/fun_result_table.html Calculates dates for two days prior to today and one day after today, then uses the `dateToString` function to format these dates and set them as the default values for the start and end time input fields. ```javascript var day1 = new Date(); day1.setDate(day1.getDate() - 2); var day2 = new Date(); day2.setDate(day2.getDate() + 1); $("#start_time").val(dateToString(day1)); $("#end_time").val(dateToString(day2)); ``` -------------------------------- ### Controlling Auto-Refresh for Speed Stats (JavaScript) Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/fun_result_table.html These functions manage the automatic refreshing of the speed statistics display. `autoFreshResult` triggers a stats query. `startRun` begins the auto-refresh interval and updates the UI button. `stopRun` clears the interval and updates the UI button. `startOrStop` toggles between starting and stopping the auto-refresh. ```javascript function autoFreshResult() { if (currentColName === undefined) { return; } queryResult(currentColName, 0, false); } ``` ```javascript function startRun() { $("#autoFresh").text("自动刷新中"); $("#autoFresh").removeClass("btn-danger"); $("#autoFresh").addClass("btn-success"); iid = setInterval(autoFreshResult, 5000); runStatus = 1; } ``` ```javascript function stopRun() { $("#autoFresh").text("暂停刷新了"); $("#autoFresh").removeClass("btn-success"); $("#autoFresh").addClass("btn-danger"); clearInterval(iid); runStatus = 0; } ``` ```javascript function startOrStop() { if (runStatus === 1) { stopRun(); } else { startRun(); } } ``` ```javascript updateTopText(); updateQueryText(); setInterval(updateQueryText, 30000); setInterval(updateTopText, 30000); iid = setInterval(autoFreshResult, 5000); ``` -------------------------------- ### Trigger Initial Data Query on Load - Javascript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_queue_name.html This snippet ensures that the main data query function (`query`) is called as soon as the document's DOM is fully loaded and ready. This populates the table with initial data, likely for a default or empty queue selection. ```javascript $(document).ready(function (){ query() }); ``` -------------------------------- ### Fetch Queues and Populate Dropdown - Javascript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_queue_name.html This snippet executes when the document is ready. It makes an AJAX call to fetch a list of available queues from the server, populates a select dropdown element with these queues, initializes the Select2 plugin on the dropdown for enhanced search and selection, and stores the selected queue name in a global variable. ```javascript var allQueues = []; // 存储所有队列数据 var currentColName; // 页面加载完成后立即获取所有队列 $(document).ready(function () { $.ajax({ url: "{{ url_for('hearbeat_info_partion_by_queue_name')}}", data: { col_name_search: '' }, async: true, success: function (result) { allQueues = result; var html = ''; for (var item of result) { html += ''; } $("#col_name_search").html(html); // 初始化选择框的搜索功能 $("#col_name_search").select2({ placeholder: "请输入队列名称搜索...", allowClear: true, width: '500px' }); // 监听选择变化 $("#col_name_search").on('change', function () { var selectedQueue = $(this).val(); console.log("Selected queue:", selectedQueue); currentColName = selectedQueue; // if(selectedQueue) { // queryResult(selectedQueue, 0, true); // } }); } }); }); ``` -------------------------------- ### Fetch and Populate IP/Queue Select - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_ip.html This script block executes when the document is ready. It fetches a list of available IPs or queues from the server via an AJAX call to the `hearbeat_info_partion_by_ip` endpoint. The results are stored, used to populate a select dropdown element (`#col_name_search`), and the select element is then initialized with the Select2 library for enhanced search and selection functionality. A change listener is also set up, although the data query logic within it is currently commented out. ```javascript // 在现有的变量声明后添加 var allQueues = []; // 存储所有队列数据 var currentColName; // 页面加载完成后立即获取所有队列 $(document).ready(function () { $.ajax({ url: "{{ url_for('hearbeat_info_partion_by_ip')}}", data: { col_name_search: '' }, async: true, success: function (result) { allQueues = result; var html = ''; for (var item of result) { html += ''; } $("#col_name_search").html(html); // 初始化选择框的搜索功能 $("#col_name_search").select2({ placeholder: "请输入ip名称搜索...", allowClear: true, width: '500px' }); // 监听选择变化 $("#col_name_search").on('change', function () { var selectedQueue = $(this).val(); console.log("Selected queue:", selectedQueue); currentColName = selectedQueue; // if(selectedQueue) { // queryResult(selectedQueue, 0, true); // } }); } }); }); ``` -------------------------------- ### Initialize UI Components - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/fun_result_table.html Initializes global variables for queue data and status, and configures the datetimepicker plugin for date/time input fields with specific format and localization settings. ```javascript var allQueues = []; var currentColName; var runStatus = 1; $(document).ready(function () { $('#start_time, #end_time').datetimepicker({ format: 'YYYY-MM-DD HH:mm:ss', locale: 'zh-cn', sideBySide: true, showClear: true, showClose: true, showTodayButton: true, icons: { time: 'fa fa-clock-o', date: 'fa fa-calendar', up: 'fa fa-chevron-up', down: 'fa fa-chevron-down', previous: 'fa fa-chevron-left', next: 'fa fa-chevron-right', today: 'fa fa-crosshairs', clear: 'fa fa-trash', close: 'fa fa-times' } }); }); ``` -------------------------------- ### Initial Data Query on Load - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_ip.html This simple script block ensures that the main data query function (`query()`) is called immediately after the document is fully loaded and ready. This populates the data table with initial information when the page is first accessed. ```javascript $(document).ready(function (){ query() }); ``` -------------------------------- ### Initialize Dashboard Data and UI Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/index_backup.html This script block initializes the dashboard upon page load. It fetches the list of task queues from the server, populates a searchable dropdown using Select2, sets default date range values, defines helper functions for string formatting and date conversion, and includes core functions for querying task results and updating statistics via AJAX. ```javascript // 在现有的变量声明后添加 var allQueues = []; // 存储所有队列数据 var currentColName; // 页面加载完成后立即获取所有队列 $(document).ready(function() { $.ajax({ url: "{{ url_for('query_cols_view')}}", data: {col_name_search: ''}, async: true, success: function (result) { allQueues = result; var html = ''; for (var item of result) { html += ''; } $("#col_name_search").html(html); // 初始化选择框的搜索功能 $("#col_name_search").select2({ placeholder: "请输入队列名称搜索...", allowClear: true, width: '300px' }); // 监听选择变化 $("#col_name_search").on('change', function() { var selectedQueue = $(this).val(); console.log("Selected queue:", selectedQueue); currentColName = selectedQueue; // if(selectedQueue) { // queryResult(selectedQueue, 0, true); // } }); } }); }); String.prototype.format = function () { var values = arguments; return this.replace(/\{(\d+)\}/g, function (match, index) { if (values.length > index) { return values[index]; } else { return ""; } }); }; function dateToString(date) { const year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); let hour = date.getHours(); let minute = date.getMinutes(); let second = date.getSeconds(); month = month > 9 ? month : ('0' + month); day = day > 9 ? day : ('0' + day); hour = hour > 9 ? hour : ('0' + hour); minute = minute > 9 ? minute : ('0' + minute); second = second > 9 ? second : ('0' + second); return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second; } //昨天的时间 var day1 = new Date(); day1.setDate(day1.getDate() - 2); //明天的时间 var day2 = new Date(); day2.setDate(day2.getDate() + 1); $("#start_time").val(dateToString(day1)); $("#end_time").val(dateToString(day2)); useAsync = false; //searchCols(); useAsync = true; function queryResult(col_name, page, manualOperate) { $('#echartsArea').css('display','none'); currentColName = col_name; if (manualOperate === true){ document.getElementById('table').style.display = 'block'; } $.ajax({ url: "{{ url_for('query_result_view')}}", data: { col_name: col_name, start_time: $("#start_time").val(), end_time: $("#end_time").val(), is_success: $("#sucess_status").val(), function_params: $("#params").val(), page: page }, async: useAsync, success: function (result, status) { // console.info(result); var html = ' \n' + ' \n' + ' 执行机器-进程-脚本\n' + ' 函数名称\n' + ' 函数入参\n' + ' 函数结果\n' + ' 消息发布时间\n' + ' 开始执行时间\n' + ' 消耗时间(秒)\n' + ' 执行次数(重试)\n' + ' 运行状态\n' + ' 是否成功\n' + ' 错误原因\n' + ' 线程(协程)数\n' + ' \n' + ' ' + ''; for (var item of result) { // console.info(item); var displayLevel = "success"; if (item.run_times > 1) { displayLevel = "warning"; } if (item.success === false) { displayLevel = "danger"; } var tr = ' \n' + ' {1}\n' + ' {2}\n' + ' {3}\n' + ' {4}\n' + ' {5}\n' + ' {6}\n' + ' {7}\n' + ' {8}\n' + ' {9}\n' + ' {10}\n' + ' {11}\n' + ' {12}\n' + ' '; var successText = item.success === true ? "成功" : "失败"; var run_status_text = item.run_status; if (item.run_status==="running"){ successText = "未完成"; displayLevel = "info"; if ( Date.now() /1000 - item.time_start > 600) { run_status_text = "running?"; } } var time_start_obj = new Date(item.time_start * 1000); var time_start_str = dateToString(time_start_obj); tr = tr.format(displayLevel, item.host_process + ' - ' + item.script_name, item.function, item.params_str, item.result,item.publish_time_str, time_start_str,item.time_cost, item.run_times, run_status_text,successText, item.exception, item.total_thread); html += tr; } html += ''; $("#table").html(html); // document.getElementById('echartsArea').style.display = 'none'; } }); if (manualOperate === true) { updateQueryText() } } function updateQueryText() { $.ajax({ url: "{{ url_for('speed_stats')}}", data: { col_name: currentColName, start_time: $("#start_time").val(), end_time: $("#end_time").val() }, async: useAsync, success: function (result, status) { var msg = '{0}队列,所选查询时间范围内运行成功了{1}次,失败了{2}次'.format(currentColName,result.success_num, result.fail_num); console.info(msg); $('#resultInfoTex').html(msg); } }) } // queryResult(currentColName, 0, true); setInterval(updateQueryText, 30000); function updateTopText() { if (currentColName===undefined) { return; } var t1 = new Date(new Date().getTime() - 60000); var t2 = new Date(); $.ajax({ url: "{{ url_for('" ``` -------------------------------- ### Instantiating and Using Person Class (JavaScript) Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/index_backup.html This snippet demonstrates how to create a new instance of the Person class with the name "laotie" and age 88. It then calls the say() method on the created object and logs the returned string to the console. ```JavaScript var obj = new Person("laotie", 88); console.log(obj.say());//我的名字叫laotie今年88岁了 ``` -------------------------------- ### Fetch Heartbeat Data and Initialize Table - Javascript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_queue_name.html This function makes an AJAX call to fetch detailed heartbeat and statistics data for the queue currently stored in the `currentColName` variable. Upon successful retrieval, it initializes a Tabulator table with the received data, defining columns, theme, layout, pagination, and localization settings to display the consumer information. ```javascript function query() { $.ajax({ url: "{{ url_for('hearbeat_info_by_queue_name')}}", data: { queue_name: currentColName }, async: true, success: function (result) { console.info(result); // 创建表格 var table = new Tabulator("#result-table", { theme: "bootstrap3", data: result, // layout: "fitColumns", layout: "fitDataTable", // 改为 fitDataTable responsiveLayout: false, // 禁用响应式布局 columns: [ {title: "

队列名称", field: "queue_name"}, {title: "

消费函数", field: "consuming_function"}, {title: "

主机名", field: "computer_name"}, {title: "

IP地址", field: "computer_ip"}, {title: "

进程ID", field: "process_id"}, {title: "

启动时间", field: "start_datetime_str","width":200}, {title: "

最近心跳时间", field: "hearbeat_datetime_str","width":200}, {title:"近10秒
运行完成
消息个数",field:"last_x_s_execute_count", formatter:"html","width":100}, {title:"近10秒
运行失败
消息个数",field:"last_x_s_execute_count_fail", formatter:"html","width":100}, {title:"近10秒
函数运行
平均耗时",field:"last_x_s_avarage_function_spend_time", formatter:"html","width":100}, {title:"累计
运行完成
消息个数",field:"total_consume_count_from_start", formatter:"html","width":100}, {title:"累计
运行失败
消息个数",field:"total_consume_count_from_start_fail", formatter:"html","width":100}, {title:"累计
函数运行
平均耗时",field:"avarage_function_spend_time_from_start", formatter:"html","width":100}, {title: "

代码文件", field: "code_filename"}, // {title: "

consumer_id", field: "consumer_id"}, {title: "

consumer_uuid", field: "consumer_uuid"} ], pagination: true, paginationSize: 1000, locale: true, langs: { "zh-cn": { "pagination": { "first": "首页", "first_title": "首页", "last": "末页", "last_title": "末页", "prev": "上一页", "prev_title": "上一页", "next": "下一页", "next_title": "下一页" } } } }); } }); } ``` -------------------------------- ### Initialize Queue Select and Load Data - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/conusme_speed.html This snippet executes when the DOM is fully loaded. It makes an AJAX call to fetch a list of queues, populates a select dropdown with the results, and initializes the select dropdown with the Select2 library for enhanced search functionality. It also sets up a change listener for the dropdown. ```JavaScript // 在现有的变量声明后添加 var allQueues = []; // 存储所有队列数据 var currentColName; // 当前选中的队列名称 // 页面加载完成后立即获取所有队列 $(document).ready(function () { $.ajax({ url: "{{ url_for('query_cols_view')}}", data: { col_name_search: '' }, async: true, success: function (result) { allQueues = result; var html = ''; for (var item of result) { html += ''; } $("#col_name_search").html(html); // 初始化选择框的搜索功能 $("#col_name_search").select2({ placeholder: "请输入队列名称搜索...", allowClear: true, width: '500px' }); // 监听选择变化 $("#col_name_search").on('change', function () { var selectedQueue = $(this).val(); console.log("Selected queue:", selectedQueue); currentColName = selectedQueue; // if(selectedQueue) { // queryResult(selectedQueue, 0, true); // } }); } }); }); ``` -------------------------------- ### Build ECharts Bar Chart - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/conusme_speed.html This helper function initializes an ECharts instance on a specified DOM element and configures it to display a bar chart. It takes parameters for the chart title, legend data, x-axis data (time), and y-axis data (counts), setting up the chart options and rendering it. ```JavaScript function _buildOneChart(elementId, titelText, legendData, xData, yData) { var myChart = echarts.init(document.getElementById(elementId)); // 指定图表的配置项和数据 var option = { title: { text: titelText }, tooltip: {}, legend: { data: [legendData] }, xAxis: { type: 'category', data: xData, axisLabel: { rotate: 90, interval: 0, // formatter: function (value) { // // console.info(value); // // var v = value.split("").join("\n"); // // console.info(v); // // return v; // }, // show: true, interval: 'auto', inside: false, rotate: 90, margin: 8, formatter: null, showMinLabel: null, showMaxLabel: null, }, }, yAxis: {}, series: [{ name: legendData, type: 'bar', data: yData }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); console.info(elementId); } ``` -------------------------------- ### Fetch Data and Initialize Tabulator - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/running_consumer_by_ip.html This JavaScript function `query()` is responsible for fetching the detailed heartbeat information for consumers. It makes an AJAX request to the `hearbeat_info_by_ip` endpoint, passing the currently selected IP. Upon success, it receives the data and initializes or updates a Tabulator data table (`#result-table`) with the fetched information, configuring columns, pagination, and localization for Chinese. ```javascript function query() { $.ajax({ url: "{{ url_for('hearbeat_info_by_ip')}}", data: { ip: currentColName }, async: true, success: function (result) { console.info(result); // 创建表格 var table = new Tabulator("#result-table", { theme: "bootstrap3", data: result, // assign data to table // layout: "fitColumns", layout: "fitDataTable", // 改为 fitDataTable responsiveLayout: false, // 禁用响应式布局 columns: [ {title: "

队列名称", field: "queue_name"}, {title: "

消费函数", field: "consuming_function"}, {title: "

主机名", field: "computer_name"}, {title: "

IP地址", field: "computer_ip"}, {title: "

进程ID", field: "process_id"}, {title: "

启动时间", field: "start_datetime_str","width":200}, {title: "

最近心跳时间", field: "hearbeat_datetime_str","width":200}, {title:"近10秒
运行完成
消息个数",field:"last_x_s_execute_count", formatter:"html","width":100}, {title:"近10秒
运行失败
消息个数",field:"last_x_s_execute_count_fail", formatter:"html","width":100}, {title:"近10秒
函数运行
平均耗时",field:"last_x_s_avarage_function_spend_time", formatter:"html","width":100}, {title:"累计
运行完成
消息个数",field:"total_consume_count_from_start", formatter:"html","width":100}, {title:"累计
运行失败
消息个数",field:"total_consume_count_from_start_fail", formatter:"html","width":100}, {title:"累计
函数运行
平均耗时",field:"avarage_function_spend_time_from_start", formatter:"html","width":100}, {title: "

代码文件", field: "code_filename"}, // {title: "

consumer_id", field: "consumer_id"}, {title: "

consumer_uuid", field: "consumer_uuid"}, ], pagination: true, paginationSize: 1000, locale: true, langs: { "zh-cn": { "pagination": { "first": "首页", "first_title": "首页", "last": "末页", "last_title": "末页", "prev": "上一页", "prev_title": "上一页", "next": "下一页", "next_title": "下一页" } } } }); /* result 例如 [ { "code_filename": "d:/codes/funboost/test_frame/test_function_status_result_persist/test_persist.py", "computer_ip": "10.0.133.57", "computer_name": "LAPTOP-7V78BBO2", "consumer_id": 1462882757512, "consumer_uuid": "88f568f7-9723-48ef-9cac-0370b2333a49", "consuming_function": "f2", "hearbeat_datetime_str": "2025-02-25 17:28:36", "hearbeat_timestamp": 1740475716.783474, "process_id": 34788, "queue_name": "queue_test_f02t", "start_datetime_str": "2025-02-25 16:33:19", "start_timestamp": 1740472399.4628778 }, { "code_filename": "d:/codes/funboost/test_frame/test_function_status_result_persist/test_persist.py", "computer_ip": "10.0.133.57", "computer_name": "LAPTOP-7V78BBO2", "consumer_id": 1462882671944, "consumer_uuid": "c52a8596-d632-4bac-a797-80375288f381", "consuming_function": "f", "hearbeat_datetime_str": "2025-02-25 17:28:36", "hearbeat_timestamp": 1740475716.783336, "process_id": 34788, "queue_name": "queue_test_f01t", "start_datetime_str": "2025-02-25 16:33:19", "start_timestamp": 1740472399.4503505 } ] */ } }); } ``` -------------------------------- ### Fetch & Populate Queue Select - JavaScript Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/fun_result_table.html Executes an AJAX call upon page load to retrieve available queue names, populates a dropdown list with these names and their counts, and initializes the Select2 plugin for enhanced search and selection functionality. ```javascript $(document).ready(function () { $.ajax({ url: "{{ url_for('query_cols_view')}}", data: { col_name_search: '' }, async: true, success: function (result) { allQueues = result; var html = ''; for (var item of result) { html += ''; } $("#col_name_search").html(html); $("#col_name_search").select2({ placeholder: "请输入队列名称搜索...", allowClear: true, width: '300px' }); $("#col_name_search").on('change', function () { var selectedQueue = $(this).val(); console.log("Selected queue:", selectedQueue); currentColName = selectedQueue; }); } }); }); ``` -------------------------------- ### Display Consumer Configuration Details Modal Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/queue_op.html The `showParams` function dynamically creates and displays a Bootstrap modal containing formatted JSON details of consumer parameters. It ensures that any existing modal is removed before a new one is added to prevent duplicates. ```JavaScript // Show parameters modal function showParams(params) { // If modal exists, remove it first if ($("#paramsModal").length) { $("#paramsModal").remove(); } const modalHtml = ` `; // Add modal to body $("body").append(modalHtml); // Initialize and show modal $("#paramsModal").modal({ backdrop: "static", keyboard: false }); } ``` -------------------------------- ### funboost Web Manager Features Overview Source: https://github.com/ydf0509/funboost/blob/master/README.md The funboost web manager provides a comprehensive interface for monitoring and managing distributed tasks and queues. It offers insights into function consumption, performance metrics, consumer details, and allows for direct queue operations and RPC calls. ```APIDOC funboost Web Manager Features: - Function Consumption Results: View and search real-time and historical function consumption status and results. - Consumption Speed Chart: View real-time and historical consumption speed. - Running Consumers by IP: Search for consumers based on IP address. - Queue Operations: View and operate queues, including clearing, pausing, resuming consumption, and adjusting QPS and concurrency. - Queue Operations - Consumer Details: View detailed information for all consumers of a queue. - Queue Operations - Consumption Curve Chart: View various consumption metrics. - RPC Calls: Publish messages to 30 types of message queues from the web page and retrieve function execution results; get results by task ID. ``` -------------------------------- ### Handle Page Loading and Navigation (JavaScript/jQuery) Source: https://github.com/ydf0509/funboost/blob/master/funboost/function_result_web/templates/index.html Manages initial page loading based on URL parameters, handles clicks on navigation links to load content into an iframe via AJAX, updates the active navigation link state, and controls the logout confirmation modal. ```JavaScript $(document).ready(function () { // 检查URL参数是否指定了页面 var urlParams = new URLSearchParams(window.location.search); var pageName = urlParams.get('page'); // 初始加载页面 if (pageName) { // 根据URL参数加载页面 loadPage('/tpl/' + pageName + '.html'); // 设置对应导航为active $('.sidebar .nav-link').removeClass('active'); $('.sidebar .nav-link\[href="/?page=' + pageName + '"\]').addClass('active'); } else { // 默认加载队列操作页面 loadPage('/tpl/queue_op.html'); } // 导航栏点击事件 $('.sidebar .nav-link').click(function (e) { // 不阻止默认行为,允许页面跳转 // e.preventDefault(); // 移除所有导航项的 active 类 $('.sidebar .nav-link').removeClass('active'); // 为当前点击的导航项添加 active 类 $(this).addClass('active'); // 获取要加载的页面文件名 const targetPage = $(this).data('target'); // 加载页面内容 loadPage(targetPage); }); // 加载页面内容的函数 function loadPage(page) { $.ajax({ url: page, method: 'GET', success: function (data) { $('#content').attr('src', page); }, error: function () { $('#content').html('

Error loading page.

'); } }); } // 退出登录确认 $('#logoutBtn').click(function(e) { e.preventDefault(); $('#logoutModal').modal('show'); }); $('#confirmLogout').click(function() { window.location.href = '/logout'; }); }); ```