功能: 集成 rclone 高级传输特性 + 全 70+ 后端支持

1. 失败自动重试:rclone Pacer 指数退避,默认 10 次底层 HTTP 重试
2. 带宽限制:配置 bandwidth_limit + Settings 运行时可调
3. 上传实时进度:progressReader + LogHub SSE 推送字节级进度/速率
4. 存储空间查询:StorageAbout 可选接口,GetUsage 返回远端真实空间
5. 全 rclone 后端:backend/all 引入 70+ 后端,新增 rclone 存储类型,
   API 驱动的可搜索后端选择器 + 动态配置表单
This commit is contained in:
Awuqing
2026-03-31 23:37:59 +08:00
parent cf5740b573
commit 1003302bdd
23 changed files with 1220 additions and 74 deletions

View File

@@ -1,6 +1,7 @@
package backup
import (
"fmt"
"sync"
"time"
)
@@ -99,6 +100,41 @@ func (h *LogHub) Complete(recordID uint, status string) {
}
}
// AppendProgress 推送上传进度事件(节流:每个 recordID 每 500ms 最多一次,最终值始终推送)。
func (h *LogHub) AppendProgress(recordID uint, progress ProgressInfo) {
h.mu.Lock()
defer h.mu.Unlock()
state := h.ensureState(recordID)
// 节流:距上次 progress 事件不足 500ms 且未完成则跳过100% 始终推送)
now := time.Now().UTC()
isFinal := progress.Percent >= 100
if !isFinal && len(state.events) > 0 {
last := state.events[len(state.events)-1]
if last.Progress != nil && now.Sub(last.Timestamp) < 500*time.Millisecond {
return
}
}
state.nextSequence++
event := LogEvent{
RecordID: recordID,
Sequence: state.nextSequence,
Level: "progress",
Message: fmt.Sprintf("上传进度: %.1f%%", progress.Percent),
Timestamp: now,
Status: state.status,
Progress: &progress,
}
state.events = append(state.events, event)
for _, subscriber := range state.subscribers {
select {
case subscriber <- event:
default:
}
}
}
func (h *LogHub) ensureState(recordID uint) *logStreamState {
state, ok := h.streams[recordID]
if ok {

View File

@@ -41,13 +41,23 @@ type RunResult struct {
}
type LogEvent struct {
RecordID uint `json:"recordId"`
Sequence int64 `json:"sequence"`
Level string `json:"level"`
Message string `json:"message"`
Timestamp time.Time `json:"timestamp"`
Completed bool `json:"completed"`
Status string `json:"status"`
RecordID uint `json:"recordId"`
Sequence int64 `json:"sequence"`
Level string `json:"level"`
Message string `json:"message"`
Timestamp time.Time `json:"timestamp"`
Completed bool `json:"completed"`
Status string `json:"status"`
Progress *ProgressInfo `json:"progress,omitempty"`
}
// ProgressInfo 描述上传进度,通过 SSE 实时推送给前端。
type ProgressInfo struct {
BytesSent int64 `json:"bytesSent"`
TotalBytes int64 `json:"totalBytes"`
Percent float64 `json:"percent"`
SpeedBps float64 `json:"speedBps"` // bytes/sec
TargetName string `json:"targetName"`
}
type LogWriter interface {