♻️ refactor(podkop): update command scheduling and priority handling

This commit is contained in:
Ivan K
2025-05-22 11:09:02 +03:00
parent f1954df83b
commit 04af8c9649
3 changed files with 62 additions and 53 deletions

View File

@@ -72,20 +72,20 @@ const FETCH_TIMEOUT = 10000; // 10 seconds
const BUTTON_FEEDBACK_TIMEOUT = 1000; // 1 second const BUTTON_FEEDBACK_TIMEOUT = 1000; // 1 second
const DIAGNOSTICS_INITIAL_DELAY = 100; // 100 milliseconds const DIAGNOSTICS_INITIAL_DELAY = 100; // 100 milliseconds
// Массив задержек для приоритетов выполнения команд в диагностике (в миллисекундах) // Интервалы планирования команд в диагностике (в миллисекундах)
const RUN_PRIORITY = [ const COMMAND_SCHEDULING = {
0, // Приоритет 0 - Критический (выполняется немедленно) P0_PRIORITY: 0, // Наивысший приоритет (без задержки)
100, // Приоритет 1 - Очень высокий P1_PRIORITY: 100, // Очень высокий приоритет
300, // Приоритет 2 - Высокий P2_PRIORITY: 300, // Высокий приоритет
500, // Приоритет 3 - Выше среднего P3_PRIORITY: 500, // Выше среднего
700, // Приоритет 4 - Средний P4_PRIORITY: 700, // Стандартный приоритет
900, // Приоритет 5 - Ниже среднего P5_PRIORITY: 900, // Ниже среднего
1100, // Приоритет 6 - Низкий P6_PRIORITY: 1100, // Низкий приоритет
1300, // Приоритет 7 - Очень низкий P7_PRIORITY: 1300, // Очень низкий приоритет
1500, // Приоритет 8 - Фоновый P8_PRIORITY: 1500, // Фоновое выполнение
1700, // Приоритет 9 - Отложенный P9_PRIORITY: 1700, // Выполнение в режиме простоя
1900 // Приоритет 10 - Наименее важный P10_PRIORITY: 1900 // Наименьший приоритет
]; };
return baseclass.extend({ return baseclass.extend({
STATUS_COLORS, STATUS_COLORS,
@@ -102,6 +102,6 @@ return baseclass.extend({
FETCH_TIMEOUT, FETCH_TIMEOUT,
BUTTON_FEEDBACK_TIMEOUT, BUTTON_FEEDBACK_TIMEOUT,
DIAGNOSTICS_INITIAL_DELAY, DIAGNOSTICS_INITIAL_DELAY,
RUN_PRIORITY, COMMAND_SCHEDULING,
CACHE_TIMEOUT CACHE_TIMEOUT
}); });

View File

@@ -44,7 +44,13 @@ function safeExec(command, args, priority, callback, timeout = constants.COMMAND
// Helper functions for handling checks // Helper functions for handling checks
function runCheck(checkFunction, priority, callback) { function runCheck(checkFunction, priority, callback) {
priority = (typeof priority === 'number') ? priority : 0; // Default to highest priority execution if priority is not provided or invalid
let schedulingDelay = constants.COMMAND_SCHEDULING.P0_PRIORITY;
// If priority is a string, try to get the corresponding delay value
if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) {
schedulingDelay = constants.COMMAND_SCHEDULING[priority];
}
const executeCheck = async () => { const executeCheck = async () => {
try { try {
@@ -62,7 +68,7 @@ function runCheck(checkFunction, priority, callback) {
}; };
if (callback && typeof callback === 'function') { if (callback && typeof callback === 'function') {
setTimeout(executeCheck, constants.RUN_PRIORITY[priority]); setTimeout(executeCheck, schedulingDelay);
return; return;
} else { } else {
return executeCheck(); return executeCheck();
@@ -70,7 +76,13 @@ function runCheck(checkFunction, priority, callback) {
} }
function runAsyncTask(taskFunction, priority) { function runAsyncTask(taskFunction, priority) {
priority = (typeof priority === 'number') ? priority : 0; // Default to highest priority execution if priority is not provided or invalid
let schedulingDelay = constants.COMMAND_SCHEDULING.P0_PRIORITY;
// If priority is a string, try to get the corresponding delay value
if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) {
schedulingDelay = constants.COMMAND_SCHEDULING[priority];
}
setTimeout(async () => { setTimeout(async () => {
try { try {
@@ -78,7 +90,7 @@ function runAsyncTask(taskFunction, priority) {
} catch (error) { } catch (error) {
console.error('Async task error:', error); console.error('Async task error:', error);
} }
}, constants.RUN_PRIORITY[priority]); }, schedulingDelay);
} }
// Helper Functions for UI and formatting // Helper Functions for UI and formatting
@@ -151,21 +163,12 @@ async function checkFakeIP() {
async function checkFakeIPCLI() { async function checkFakeIPCLI() {
try { try {
return new Promise((resolve) => { return new Promise((resolve) => {
safeExec('/usr/bin/podkop', ['get_sing_box_status'], 0, singboxStatusResult => { safeExec('nslookup', ['-timeout=2', constants.FAKEIP_CHECK_DOMAIN, '127.0.0.42'], 'P0_PRIORITY', result => {
const singboxStatus = JSON.parse(singboxStatusResult.stdout || '{"running":0,"dns_configured":0}'); if (result.stdout && result.stdout.includes('198.18')) {
resolve(createStatus('working', 'working on router', 'SUCCESS'));
if (!singboxStatus.running) { } else {
resolve(createStatus('not_working', 'sing-box not running', 'ERROR')); resolve(createStatus('not_working', 'not working on router', 'ERROR'));
return;
} }
safeExec('nslookup', ['-timeout=2', constants.FAKEIP_CHECK_DOMAIN, '127.0.0.42'], 0, result => {
if (result.stdout && result.stdout.includes('198.18')) {
resolve(createStatus('working', 'working on router', 'SUCCESS'));
} else {
resolve(createStatus('not_working', 'not working on router', 'ERROR'));
}
});
}); });
}); });
} catch (error) { } catch (error) {
@@ -176,7 +179,7 @@ async function checkFakeIPCLI() {
function checkDNSAvailability() { function checkDNSAvailability() {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
try { try {
safeExec('/usr/bin/podkop', ['check_dns_available'], 0, dnsStatusResult => { safeExec('/usr/bin/podkop', ['check_dns_available'], 'P0_PRIORITY', dnsStatusResult => {
if (!dnsStatusResult || !dnsStatusResult.stdout) { if (!dnsStatusResult || !dnsStatusResult.stdout) {
return resolve({ return resolve({
remote: createStatus('error', 'DNS check timeout', 'WARNING'), remote: createStatus('error', 'DNS check timeout', 'WARNING'),
@@ -319,7 +322,7 @@ function showConfigModal(command, title) {
let formattedOutput = ''; let formattedOutput = '';
if (command === 'global_check') { if (command === 'global_check') {
safeExec('/usr/bin/podkop', [command], 0, res => { safeExec('/usr/bin/podkop', [command], 'P0_PRIORITY', res => {
formattedOutput = formatDiagnosticOutput(res.stdout || _('No output')); formattedOutput = formatDiagnosticOutput(res.stdout || _('No output'));
try { try {
@@ -381,7 +384,7 @@ function showConfigModal(command, title) {
} }
}); });
} else { } else {
safeExec('/usr/bin/podkop', [command], 0, res => { safeExec('/usr/bin/podkop', [command], 'P0_PRIORITY', res => {
formattedOutput = formatDiagnosticOutput(res.stdout || _('No output')); formattedOutput = formatDiagnosticOutput(res.stdout || _('No output'));
updateModalContent(formattedOutput); updateModalContent(formattedOutput);
}); });
@@ -405,7 +408,7 @@ const ButtonFactory = {
return this.createButton({ return this.createButton({
label: config.label, label: config.label,
additionalClass: `cbi-button-${config.type || ''}`, additionalClass: `cbi-button-${config.type || ''}`,
onClick: () => safeExec('/usr/bin/podkop', [config.action]) onClick: () => safeExec('/usr/bin/podkop', [config.action], 'P0_PRIORITY')
.then(() => config.reload && location.reload()), .then(() => config.reload && location.reload()),
style: config.style style: config.style
}); });
@@ -415,7 +418,7 @@ const ButtonFactory = {
return this.createButton({ return this.createButton({
label: config.label, label: config.label,
additionalClass: `cbi-button-${config.type || ''}`, additionalClass: `cbi-button-${config.type || ''}`,
onClick: () => safeExec('/etc/init.d/podkop', [config.action]) onClick: () => safeExec('/etc/init.d/podkop', [config.action], 'P0_PRIORITY')
.then(() => config.reload && location.reload()), .then(() => config.reload && location.reload()),
style: config.style style: config.style
}); });
@@ -620,7 +623,7 @@ function updateTextElement(elementId, content) {
async function updateDiagnostics() { async function updateDiagnostics() {
// Podkop Status check // Podkop Status check
safeExec('/usr/bin/podkop', ['get_status'], 0, result => { safeExec('/usr/bin/podkop', ['get_status'], 'P0_PRIORITY', result => {
try { try {
const parsedPodkopStatus = JSON.parse(result.stdout || '{"enabled":0,"status":"error"}'); const parsedPodkopStatus = JSON.parse(result.stdout || '{"enabled":0,"status":"error"}');
@@ -664,7 +667,7 @@ async function updateDiagnostics() {
}); });
// Sing-box Status check // Sing-box Status check
safeExec('/usr/bin/podkop', ['get_sing_box_status'], 0, result => { safeExec('/usr/bin/podkop', ['get_sing_box_status'], 'P0_PRIORITY', result => {
try { try {
const parsedSingboxStatus = JSON.parse(result.stdout || '{"running":0,"enabled":0,"status":"error"}'); const parsedSingboxStatus = JSON.parse(result.stdout || '{"running":0,"enabled":0,"status":"error"}');
@@ -686,25 +689,25 @@ async function updateDiagnostics() {
}); });
// Version Information checks // Version Information checks
safeExec('/usr/bin/podkop', ['show_version'], 2, result => { safeExec('/usr/bin/podkop', ['show_version'], 'P2_PRIORITY', result => {
updateTextElement('podkop-version', updateTextElement('podkop-version',
document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown')) document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown'))
); );
}); });
safeExec('/usr/bin/podkop', ['show_luci_version'], 2, result => { safeExec('/usr/bin/podkop', ['show_luci_version'], 'P2_PRIORITY', result => {
updateTextElement('luci-version', updateTextElement('luci-version',
document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown')) document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown'))
); );
}); });
safeExec('/usr/bin/podkop', ['show_sing_box_version'], 2, result => { safeExec('/usr/bin/podkop', ['show_sing_box_version'], 'P2_PRIORITY', result => {
updateTextElement('singbox-version', updateTextElement('singbox-version',
document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown')) document.createTextNode(result.stdout ? result.stdout.trim() : _('Unknown'))
); );
}); });
safeExec('/usr/bin/podkop', ['show_system_info'], 2, result => { safeExec('/usr/bin/podkop', ['show_system_info'], 'P2_PRIORITY', result => {
if (result.stdout) { if (result.stdout) {
updateTextElement('openwrt-version', updateTextElement('openwrt-version',
document.createTextNode(result.stdout.split('\n')[1].trim()) document.createTextNode(result.stdout.split('\n')[1].trim())
@@ -719,7 +722,7 @@ async function updateDiagnostics() {
}); });
// FakeIP and DNS status checks // FakeIP and DNS status checks
runCheck(checkFakeIP, 3, result => { runCheck(checkFakeIP, 'P3_PRIORITY', result => {
updateTextElement('fakeip-browser-status', updateTextElement('fakeip-browser-status',
E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [
result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ',
@@ -728,7 +731,7 @@ async function updateDiagnostics() {
); );
}); });
runCheck(checkFakeIPCLI, 3, result => { runCheck(checkFakeIPCLI, 'P8_PRIORITY', result => {
updateTextElement('fakeip-router-status', updateTextElement('fakeip-router-status',
E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [
result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ',
@@ -737,7 +740,7 @@ async function updateDiagnostics() {
); );
}); });
runCheck(checkDNSAvailability, 4, result => { runCheck(checkDNSAvailability, 'P4_PRIORITY', result => {
if (result.error) { if (result.error) {
updateTextElement('dns-remote-status', updateTextElement('dns-remote-status',
E('span', { style: `color: ${constants.STATUS_COLORS.WARNING}` }, '! DNS check error') E('span', { style: `color: ${constants.STATUS_COLORS.WARNING}` }, '! DNS check error')
@@ -762,14 +765,14 @@ async function updateDiagnostics() {
} }
}); });
runCheck(checkBypass, 1, result => { runCheck(checkBypass, 'P1_PRIORITY', result => {
updateTextElement('bypass-status', updateTextElement('bypass-status',
E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [
result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ',
result.error ? 'check error' : result.message result.error ? 'check error' : result.message
]) ])
); );
}); }, 'P1_PRIORITY');
// Config name // Config name
runAsyncTask(async () => { runAsyncTask(async () => {
@@ -797,7 +800,7 @@ async function updateDiagnostics() {
} catch (e) { } catch (e) {
console.error('Error getting config name from UCI:', e); console.error('Error getting config name from UCI:', e);
} }
}, 1); }, 'P1_PRIORITY');
} }
function createDiagnosticsSection(mainSection) { function createDiagnosticsSection(mainSection) {

View File

@@ -16,7 +16,7 @@ let errorPollTimer = null;
// Helper function to fetch errors from the podkop command // Helper function to fetch errors from the podkop command
async function getPodkopErrors() { async function getPodkopErrors() {
return new Promise(resolve => { return new Promise(resolve => {
safeExec('/usr/bin/podkop', ['check_logs'], 0, result => { safeExec('/usr/bin/podkop', ['check_logs'], 'P0_PRIORITY', result => {
if (!result || !result.stdout) return resolve([]); if (!result || !result.stdout) return resolve([]);
const logs = result.stdout.split('\n'); const logs = result.stdout.split('\n');
@@ -40,7 +40,13 @@ function showErrorNotification(error, isMultiple = false) {
// Helper function for command execution with prioritization // Helper function for command execution with prioritization
function safeExec(command, args, priority, callback, timeout = constants.COMMAND_TIMEOUT) { function safeExec(command, args, priority, callback, timeout = constants.COMMAND_TIMEOUT) {
priority = (typeof priority === 'number') ? priority : 0; // Default to highest priority execution if priority is not provided or invalid
let schedulingDelay = constants.COMMAND_SCHEDULING.P0_PRIORITY;
// If priority is a string, try to get the corresponding delay value
if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) {
schedulingDelay = constants.COMMAND_SCHEDULING[priority];
}
const executeCommand = async () => { const executeCommand = async () => {
try { try {
@@ -76,7 +82,7 @@ function safeExec(command, args, priority, callback, timeout = constants.COMMAND
}; };
if (callback && typeof callback === 'function') { if (callback && typeof callback === 'function') {
setTimeout(executeCommand, constants.RUN_PRIORITY[priority]); setTimeout(executeCommand, schedulingDelay);
return; return;
} }
else { else {