fix(scan): two-phase progress + hosts_processed; clarify status at 99% SNMP tail
Made-with: Cursor
This commit is contained in:
+57
-17
@@ -33,6 +33,24 @@ func NewRunner(store Store, cfg RunnerConfig) *Runner {
|
||||
return &Runner{store: store, cfg: cfg}
|
||||
}
|
||||
|
||||
// scanProgressBlend: часть прогресса за ping/порты (быстро), основная — за полное завершение хоста (SNMP и т.д.).
|
||||
// Пока не все хосты завершены полностью, процент не поднимается выше 99 — чтобы не казалось, что скан «завис на 100%».
|
||||
func scanProgressBlend(quickDone, fullDone, total int) int {
|
||||
if total <= 0 {
|
||||
return 100
|
||||
}
|
||||
if fullDone >= total {
|
||||
return 100
|
||||
}
|
||||
// Округление к ближайшему проценту, иначе 15*256+85*253 даёт 98 при ожидании «почти 99».
|
||||
num := 15*quickDone + 85*fullDone
|
||||
p := (num + total/2) / total
|
||||
if p >= 99 {
|
||||
return 99
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (r *Runner) Start(job ScanJob) {
|
||||
go r.run(job)
|
||||
}
|
||||
@@ -64,7 +82,7 @@ func (r *Runner) run(job ScanJob) {
|
||||
_, _ = r.store.UpdateScan(job.ID, ScanUpdate{
|
||||
Status: "done",
|
||||
Progress: 100,
|
||||
Stats: ScanStats{HostsTotal: 0, HostsUp: 0},
|
||||
Stats: ScanStats{},
|
||||
FinishedAt: &finished,
|
||||
})
|
||||
return
|
||||
@@ -76,11 +94,29 @@ func (r *Runner) run(job ScanJob) {
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
var done int
|
||||
var quickDone int // ping (+ TCP-порты)
|
||||
var fullDone int // полностью, включая SNMP
|
||||
var up int
|
||||
workCh := make(chan string)
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
pushProgress := func() {
|
||||
mu.Lock()
|
||||
q, f, u := quickDone, fullDone, up
|
||||
mu.Unlock()
|
||||
prog := scanProgressBlend(q, f, total)
|
||||
_, _ = r.store.UpdateScan(job.ID, ScanUpdate{
|
||||
Status: "running",
|
||||
Progress: prog,
|
||||
Stats: ScanStats{
|
||||
HostsTotal: total,
|
||||
HostsUp: u,
|
||||
HostsPingPhaseDone: q,
|
||||
HostsProcessed: f,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
worker := func() {
|
||||
defer wg.Done()
|
||||
for ip := range workCh {
|
||||
@@ -101,6 +137,15 @@ func (r *Runner) run(job ScanJob) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
if isUp {
|
||||
up++
|
||||
}
|
||||
quickDone++
|
||||
mu.Unlock()
|
||||
pushProgress()
|
||||
|
||||
if isUp && r.cfg.SNMPEnabled {
|
||||
snmpRes, lldpRes, ifRes, portDevRes := probeSNMPAndLLDP(ip, r.cfg.SNMPCommunity, checkedAt, job.Options.PingTimeoutMS)
|
||||
_ = r.store.SaveSNMPResult(job.ID, snmpRes)
|
||||
@@ -122,19 +167,9 @@ func (r *Runner) run(job ScanJob) {
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
done++
|
||||
if isUp {
|
||||
up++
|
||||
}
|
||||
progress := done * 100 / total
|
||||
stats := ScanStats{HostsTotal: total, HostsUp: up}
|
||||
fullDone++
|
||||
mu.Unlock()
|
||||
|
||||
_, _ = r.store.UpdateScan(job.ID, ScanUpdate{
|
||||
Status: "running",
|
||||
Progress: progress,
|
||||
Stats: stats,
|
||||
})
|
||||
pushProgress()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +186,14 @@ func (r *Runner) run(job ScanJob) {
|
||||
|
||||
finished := time.Now().UTC()
|
||||
_, _ = r.store.UpdateScan(job.ID, ScanUpdate{
|
||||
Status: "done",
|
||||
Progress: 100,
|
||||
Stats: ScanStats{HostsTotal: total, HostsUp: up},
|
||||
Status: "done",
|
||||
Progress: 100,
|
||||
Stats: ScanStats{
|
||||
HostsTotal: total,
|
||||
HostsUp: up,
|
||||
HostsPingPhaseDone: total,
|
||||
HostsProcessed: total,
|
||||
},
|
||||
FinishedAt: &finished,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user