A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys, Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun VPN routing, and a web dashboard to manage it all. Free & open forever to self-host; optional paid hosted services fund it. See PROMISE.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
228 lines
6.0 KiB
JavaScript
Executable File
228 lines
6.0 KiB
JavaScript
Executable File
/**
|
|
* Task Router - Action routing and dispatch for individual tasks
|
|
* Handles action routing, queuing, and error management
|
|
*/
|
|
|
|
class TaskRouter {
|
|
constructor(tasksManager, actions) {
|
|
this.tasksManager = tasksManager;
|
|
this.actions = actions;
|
|
this.commandQueue = [];
|
|
this.isProcessing = false;
|
|
}
|
|
|
|
/**
|
|
* Route action to appropriate handler
|
|
*/
|
|
async routeAction(action, params = {}) {
|
|
try {
|
|
//console.log(`🎯 Routing action: ${action}`, params);
|
|
|
|
switch (action) {
|
|
case 'install':
|
|
return await this.actions.installApp(params.appName, params.config, params.resetNetwork);
|
|
|
|
case 'uninstall':
|
|
return await this.actions.uninstallApp(params.appName, params.deleteImage, params.deleteTasks);
|
|
|
|
case 'restart':
|
|
return await this.actions.restartApp(params.appName);
|
|
|
|
case 'start':
|
|
return await this.actions.startApp(params.appName);
|
|
|
|
case 'stop':
|
|
return await this.actions.stopApp(params.appName);
|
|
|
|
case 'backup':
|
|
return await this.actions.backupApp(params.appName, params.customPassword);
|
|
|
|
case 'restore':
|
|
return await this.actions.restoreApp(
|
|
params.appName,
|
|
params.location,
|
|
params.backupFile,
|
|
params.password
|
|
);
|
|
|
|
case 'delete':
|
|
return await this.actions.deleteBackup(params.appName, params.backupFile, params.deleteRemote1, params.deleteRemote2);
|
|
|
|
case 'delete_all':
|
|
return await this.actions.deleteAllBackups(params.appName, params.deleteRemote1, params.deleteRemote2);
|
|
|
|
case 'update_config':
|
|
return await this.actions.updateConfig(params.appName);
|
|
|
|
case 'config_update':
|
|
return await this.actions.configUpdate(params.changes);
|
|
|
|
case 'system_update':
|
|
return await this.actions.systemUpdate();
|
|
|
|
case 'tool':
|
|
return await this.actions.runTool(params.appName, params.toolName, params.toolArgs, params.toolLabel);
|
|
|
|
default:
|
|
throw new Error(`Unknown action: ${action}`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`❌ Action routing failed: ${error.message}`);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Queue action for execution
|
|
*/
|
|
queueAction(action, params = {}) {
|
|
const queuedTask = {
|
|
id: Date.now().toString(),
|
|
action: action,
|
|
params: params,
|
|
timestamp: new Date().toISOString(),
|
|
status: 'queued'
|
|
};
|
|
|
|
this.commandQueue.push(queuedTask);
|
|
//console.log(`📋 Queued action: ${action}`, params);
|
|
|
|
// Start processing if not already running
|
|
if (!this.isProcessing) {
|
|
this.processQueue();
|
|
}
|
|
|
|
return queuedTask.id;
|
|
}
|
|
|
|
/**
|
|
* Process the command queue
|
|
*/
|
|
async processQueue() {
|
|
if (this.isProcessing || this.commandQueue.length === 0) {
|
|
return;
|
|
}
|
|
|
|
this.isProcessing = true;
|
|
//console.log('🔄 Processing command queue...');
|
|
|
|
while (this.commandQueue.length > 0) {
|
|
const queuedTask = this.commandQueue.shift();
|
|
|
|
try {
|
|
//console.log(`⚡ Executing queued action: ${queuedTask.action}`);
|
|
await this.routeAction(queuedTask.action, queuedTask.params);
|
|
|
|
queuedTask.status = 'completed';
|
|
//console.log(`✅ Completed queued action: ${queuedTask.action}`);
|
|
|
|
} catch (error) {
|
|
queuedTask.status = 'failed';
|
|
queuedTask.error = error.message;
|
|
console.error(`❌ Failed queued action: ${queuedTask.action}`, error);
|
|
|
|
if (window.notificationSystem) {
|
|
// Pull the per-action icon if we know it; falls back to the
|
|
// generic error SVG via customIcon=null.
|
|
const typeIcon = (window.tasksManager && window.tasksManager.getTaskTypeIcon
|
|
? window.tasksManager.getTaskTypeIcon({ type: queuedTask.action })
|
|
: null)?.icon || '';
|
|
const customIcon = typeIcon ? `<span style="font-size:18px;line-height:1;">${typeIcon}</span>` : null;
|
|
window.notificationSystem.show(
|
|
`Queued action failed: ${error.message}`,
|
|
'error',
|
|
null,
|
|
null,
|
|
null,
|
|
customIcon
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.isProcessing = false;
|
|
//console.log('✅ Command queue processing complete');
|
|
}
|
|
|
|
/**
|
|
* Get queue status
|
|
*/
|
|
getQueueStatus() {
|
|
return {
|
|
isProcessing: this.isProcessing,
|
|
queueLength: this.commandQueue.length,
|
|
queuedTasks: [...this.commandQueue]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Clear the queue
|
|
*/
|
|
clearQueue() {
|
|
const clearedCount = this.commandQueue.length;
|
|
this.commandQueue = [];
|
|
|
|
if (window.notificationSystem) {
|
|
const customIcon = '<span style="font-size:18px;line-height:1;">🗑️</span>';
|
|
window.notificationSystem.show(
|
|
`Cleared ${clearedCount} queued actions`,
|
|
'info',
|
|
null,
|
|
null,
|
|
null,
|
|
customIcon
|
|
);
|
|
}
|
|
|
|
return clearedCount;
|
|
}
|
|
|
|
/**
|
|
* Get available actions
|
|
*/
|
|
getAvailableActions() {
|
|
return [
|
|
'install',
|
|
'uninstall',
|
|
'restart',
|
|
'start',
|
|
'stop',
|
|
'backup',
|
|
'delete',
|
|
'delete_all',
|
|
'update_config',
|
|
'system_update',
|
|
'tool'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Validate action parameters
|
|
*/
|
|
validateAction(action, params) {
|
|
const requiredParams = {
|
|
install: ['appName'],
|
|
uninstall: ['appName'],
|
|
restart: ['appName'],
|
|
start: ['appName'],
|
|
stop: ['appName'],
|
|
backup: ['appName'],
|
|
delete: ['appName', 'backupFile'],
|
|
update_config: ['appName'],
|
|
tool: ['appName', 'toolName']
|
|
};
|
|
|
|
const required = requiredParams[action] || [];
|
|
const missing = required.filter(param => !params[param]);
|
|
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing required parameters for ${action}: ${missing.join(', ')}`);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Export for use
|
|
window.TaskRouter = TaskRouter;
|