fix: console stays after deploy, auto-refresh, config retry
- 下发后留在控制台,显示状态提示,6秒自动刷新 - 任务页 SSE 自动连接(无需手动点击) - 总览页有执行中任务时自动刷新 - config_apply 增加 3 次重试(agent 500 时)
This commit is contained in:
parent
15f6f91fb6
commit
f2b3941e4a
@ -9,6 +9,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"3588AdminBackend/internal/config"
|
"3588AdminBackend/internal/config"
|
||||||
"3588AdminBackend/internal/models"
|
"3588AdminBackend/internal/models"
|
||||||
@ -307,13 +308,26 @@ func (s *TaskService) executeOnDevice(task *models.Task, did string) {
|
|||||||
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, "invalid payload: "+err.Error())
|
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, "invalid payload: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, code, err := s.agent.Do("PUT", dev.IP, dev.AgentPort, "/v1/config", body)
|
// Retry config apply up to 3 times (media-server may be slow to reload).
|
||||||
if err != nil {
|
var lastErr error
|
||||||
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, err.Error())
|
var lastCode int
|
||||||
|
for attempt := 0; attempt < 3; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(time.Duration(attempt) * 3 * time.Second)
|
||||||
|
s.updateDeviceStatus(task.ID, did, models.TaskRunning, float64(attempt)/3.0, fmt.Sprintf("重试 %d/2", attempt))
|
||||||
|
}
|
||||||
|
_, code, err := s.agent.Do("PUT", dev.IP, dev.AgentPort, "/v1/config", body)
|
||||||
|
if err == nil && code < 400 {
|
||||||
|
lastErr = nil; lastCode = code; break
|
||||||
|
}
|
||||||
|
lastErr = err; lastCode = code
|
||||||
|
}
|
||||||
|
if lastErr != nil {
|
||||||
|
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, lastErr.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if code >= 400 {
|
if lastCode >= 400 {
|
||||||
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, fmt.Sprintf("agent error: %d", code))
|
s.updateDeviceStatus(task.ID, did, models.TaskFailed, 0, fmt.Sprintf("agent error: %d", lastCode))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.updateDeviceStatus(task.ID, did, models.TaskSuccess, 1.0, "")
|
s.updateDeviceStatus(task.ID, did, models.TaskSuccess, 1.0, "")
|
||||||
|
|||||||
@ -1192,11 +1192,11 @@ func (u *UI) actionConsoleSave(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(taskIDs) == 1 {
|
if len(taskIDs) == 1 {
|
||||||
http.Redirect(w, r, "/ui/console?task="+taskIDs[0], http.StatusFound)
|
http.Redirect(w, r, "/ui/console?msg="+url.QueryEscape("正在下发配置...")+"&task="+taskIDs[0], http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(taskIDs) > 1 {
|
if len(taskIDs) > 1 {
|
||||||
http.Redirect(w, r, "/ui/console?task="+taskIDs[0]+"&msg="+url.QueryEscape(fmt.Sprintf("已为 %d 台设备创建下发任务", len(taskIDs))), http.StatusFound)
|
http.Redirect(w, r, "/ui/console?msg="+url.QueryEscape(fmt.Sprintf("正在为 %d 台设备下发配置...", len(taskIDs))), http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
|
|||||||
@ -375,11 +375,17 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show saved task info from URL param
|
// Show saved task info and auto-refresh from URL param
|
||||||
(function() {
|
(function() {
|
||||||
var m = location.search.match(/[?&]task=([^&]+)/);
|
var m = location.search.match(/[?&]task=([^&]+)/);
|
||||||
if (m) {
|
if (m) {
|
||||||
document.getElementById('console-status').innerHTML = '✅ 任务 ' + m[1].substring(0,8) + ' 已创建';
|
document.getElementById('console-status').innerHTML = '⏳ 任务 ' + m[1].substring(0,8) + ' 执行中,页面将自动刷新...';
|
||||||
|
setTimeout(function(){ location.href = '/ui/console'; }, 6000);
|
||||||
|
}
|
||||||
|
var msg = location.search.match(/[?&]msg=([^&]+)/);
|
||||||
|
if (msg) {
|
||||||
|
document.getElementById('console-status').innerHTML = decodeURIComponent(msg[1]);
|
||||||
|
if (!m) setTimeout(function(){ document.getElementById('console-status').innerHTML = ''; }, 5000);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@ -73,5 +73,10 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
if({{.RunningTaskCount}}>0) setTimeout(function(){location.reload()},6000);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@ -144,5 +144,13 @@ function cssEscape(s){
|
|||||||
return String(s).replace(/[^a-zA-Z0-9_-]/g, (c) => "\\"+c);
|
return String(s).replace(/[^a-zA-Z0-9_-]/g, (c) => "\\"+c);
|
||||||
}
|
}
|
||||||
syncTaskStatus();
|
syncTaskStatus();
|
||||||
|
// Auto-connect SSE and auto-refresh if task is in progress.
|
||||||
|
(function(){
|
||||||
|
var s='{{.Task.Status}}';
|
||||||
|
if(s==='running'||s==='pending'){
|
||||||
|
startSSE();
|
||||||
|
setTimeout(function(){location.reload()},8000);
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{{define "tasks"}}
|
{{define "tasks"}}
|
||||||
<div class="card">
|
<div class="card" id="tasks-container">
|
||||||
<h2>执行历史</h2>
|
<h2>执行历史</h2>
|
||||||
<div class="table-wrap" style="margin-top:10px">
|
<div class="table-wrap" style="margin-top:10px">
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user