62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package fileedit
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ProgressPrefix marks a progress line: how many of an upload's or an unzip's
|
|
// bytes are in so far, as JSON. Those two run as Jobs felis-api does not wait on,
|
|
// and the panel shows how far one has got by reading the latest such line from
|
|
// the tail of the Pod's log. Like ResultPrefix it is found by its marker, since
|
|
// the log is stdout and stderr merged.
|
|
const ProgressPrefix = "FELIS-FILES-PROGRESS: "
|
|
|
|
// Progress is one progress line.
|
|
type Progress struct {
|
|
Done int64 `json:"done"`
|
|
Total int64 `json:"total"`
|
|
}
|
|
|
|
// ThrottledProgress returns a progress func that prints to w at most once per
|
|
// every, plus the first call (the last print starts at the zero time) and the
|
|
// one that reaches the total, so the log grows by a line a second however fast
|
|
// the bytes move and still ends on the true final count. A write error is
|
|
// dropped: progress is a courtesy, and the result line that follows is what
|
|
// felis-api acts on.
|
|
func ThrottledProgress(w io.Writer, every time.Duration, now func() time.Time) func(done, total int64) {
|
|
var last time.Time
|
|
return func(done, total int64) {
|
|
t := now()
|
|
if done < total && t.Sub(last) < every {
|
|
return
|
|
}
|
|
last = t
|
|
b, _ := json.Marshal(Progress{Done: done, Total: total})
|
|
fmt.Fprintf(w, "%s%s\n", ProgressPrefix, b)
|
|
}
|
|
}
|
|
|
|
// lastProgress finds the latest well-formed progress line in a log.
|
|
func lastProgress(log string) (Progress, bool) {
|
|
var p Progress
|
|
found := false
|
|
sc := bufio.NewScanner(strings.NewReader(log))
|
|
sc.Buffer(make([]byte, 0, 4096), maxLogBytes)
|
|
for sc.Scan() {
|
|
rest, ok := strings.CutPrefix(sc.Text(), ProgressPrefix)
|
|
if !ok {
|
|
continue
|
|
}
|
|
var q Progress
|
|
if json.Unmarshal([]byte(rest), &q) == nil {
|
|
p, found = q, true
|
|
}
|
|
}
|
|
return p, found
|
|
}
|