fix(reliability): 采集器并发去重 + 备份恢复即时重载 + context 贯穿请求链
- CollectorService 安装/卸载按采集器互斥去重(重复触发不再并发 docker rm/run 互踩);删除后卸载失败留日志 - ApplyStagedBackup 替换文件后立即 Reload 内存态,消除「重启前旧内存落盘覆盖恢复文件」竞态;暂存文件名升级 lokistack.json(兼容旧名) - GetUsage/Validate 全链路 context 贯穿:请求取消即中止 SSH/k8s 查询(异步调用点显式 Background)
This commit is contained in:
1 parent
9daaf7f403
commit
572efc89a4
9 files changed
+180
-29
No files matched your search
+102
-5
@@ -264,11 +264,6 @@ func (d *JsonDB) fixUnreachableLogSourceURLs() {
|
||||
// LogSource : 查询页数据源下拉选不动(两个 option 同 value)
|
||||
// AlertRule : 规则列表出现两条同 id,编辑/删除操作命中错的那条
|
||||
// NotifyChannel: 通知渠道覆盖错对象
|
||||
func (d *JsonDB) dedupeCollectionIDs() {
|
||||
d.dedupeLogSourceIDs()
|
||||
d.dedupeAlertRuleIDs()
|
||||
d.dedupeNotifyChannelIDs()
|
||||
}
|
||||
|
||||
// dedupeAlertRuleIDs 重新编号重复的告警规则 ID。
|
||||
// 同名规则(seed 重复执行导致)只保留第一条,其余删除。
|
||||
@@ -539,6 +534,108 @@ func (d *JsonDB) migrateSchema() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Reload 从磁盘重新加载内存态(备份恢复后调用):
|
||||
// 成功解析才整体替换集合并重建 ID 序列;失败时保持原内存态并返回错误。
|
||||
// 必须在持有写锁的情况下调用。
|
||||
func (d *JsonDB) Reload() error {
|
||||
data, err := os.ReadFile(d.dataFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var fresh JsonDB
|
||||
if err := json.Unmarshal(data, &fresh); err != nil {
|
||||
return err
|
||||
}
|
||||
d.Users = fresh.Users
|
||||
d.Clusters = fresh.Clusters
|
||||
d.Hosts = fresh.Hosts
|
||||
d.Storages = fresh.Storages
|
||||
d.Deployments = fresh.Deployments
|
||||
d.Collectors = fresh.Collectors
|
||||
d.Logs = fresh.Logs
|
||||
d.Settings = fresh.Settings
|
||||
d.LogSources = fresh.LogSources
|
||||
d.AlertRules = fresh.AlertRules
|
||||
d.AlertDeliveries = fresh.AlertDeliveries
|
||||
d.NotifyChannels = fresh.NotifyChannels
|
||||
d.LogPolicyGroups = fresh.LogPolicyGroups
|
||||
d.AuditLogs = fresh.AuditLogs
|
||||
d.DailyVolumeSnapshots = fresh.DailyVolumeSnapshots
|
||||
d.SchemaVersion = fresh.SchemaVersion
|
||||
d.sequences = map[string]uint{}
|
||||
for _, u := range d.Users {
|
||||
if u.ID > d.sequences["users"] {
|
||||
d.sequences["users"] = u.ID
|
||||
}
|
||||
}
|
||||
for _, cl := range d.Clusters {
|
||||
if cl.ID > d.sequences["clusters"] {
|
||||
d.sequences["clusters"] = cl.ID
|
||||
}
|
||||
}
|
||||
for _, h := range d.Hosts {
|
||||
if h.ID > d.sequences["hosts"] {
|
||||
d.sequences["hosts"] = h.ID
|
||||
}
|
||||
}
|
||||
for _, s := range d.Storages {
|
||||
if s.ID > d.sequences["storages"] {
|
||||
d.sequences["storages"] = s.ID
|
||||
}
|
||||
}
|
||||
for _, de := range d.Deployments {
|
||||
if de.ID > d.sequences["deployments"] {
|
||||
d.sequences["deployments"] = de.ID
|
||||
}
|
||||
}
|
||||
for _, col := range d.Collectors {
|
||||
if col.ID > d.sequences["collectors"] {
|
||||
d.sequences["collectors"] = col.ID
|
||||
}
|
||||
}
|
||||
for _, l := range d.Logs {
|
||||
if l.ID > d.sequences["logs"] {
|
||||
d.sequences["logs"] = l.ID
|
||||
}
|
||||
}
|
||||
for _, g := range d.LogPolicyGroups {
|
||||
if g.ID > d.sequences["logPolicyGroups"] {
|
||||
d.sequences["logPolicyGroups"] = g.ID
|
||||
}
|
||||
}
|
||||
for _, s := range d.LogSources {
|
||||
if s.ID > d.sequences["logSources"] {
|
||||
d.sequences["logSources"] = s.ID
|
||||
}
|
||||
}
|
||||
for _, ch := range d.NotifyChannels {
|
||||
if ch.ID > d.sequences["notifyChannels"] {
|
||||
d.sequences["notifyChannels"] = ch.ID
|
||||
}
|
||||
}
|
||||
for _, r := range d.AlertRules {
|
||||
if r.ID > d.sequences["alertRules"] {
|
||||
d.sequences["alertRules"] = r.ID
|
||||
}
|
||||
}
|
||||
for _, de := range d.AlertDeliveries {
|
||||
if de.ID > d.sequences["alertDeliveries"] {
|
||||
d.sequences["alertDeliveries"] = de.ID
|
||||
}
|
||||
}
|
||||
for _, a := range d.AuditLogs {
|
||||
if a.ID > d.sequences["auditLogs"] {
|
||||
d.sequences["auditLogs"] = a.ID
|
||||
}
|
||||
}
|
||||
for _, v := range d.DailyVolumeSnapshots {
|
||||
if v.ID > d.sequences["dailyVolumeSnapshots"] {
|
||||
d.sequences["dailyVolumeSnapshots"] = v.ID
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrateLegacyDataFile 首次从历史命名(opsxloki.json / lokideploy.json)加载后,
|
||||
// 立即升级到 lokistack.json:数据原子写入新文件后删除旧文件。
|
||||
// 不迁移的话回退链会让旧文件名(旧品牌残留)一直被沿用下去。
|
||||
|
||||
Reference in new issue
Block a user