internal/issues/page.go
Rama main · réplica de lectura del repositorio original.
package issues
import (
"encoding/base64"
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/sophotechlabs/spinoza/internal/api"
)
const Shown = 50
const (
ByWorst = "worst"
ByNewest = "newest"
ByOldest = "oldest"
)
func OrderOf(asked string) string {
if asked == ByNewest || asked == ByOldest {
return asked
}
return ByWorst
}
const (
foldCeiling = 999999999
timeCeiling = 9999999999
)
func issueKey(row api.Issue, order string) string {
if order == ByNewest {
return strings.Join([]string{
countDown(secondsOf(seenAt(row.Since)), timeCeiling),
row.Cluster,
row.ID,
}, "\x00")
}
if order == ByOldest {
return strings.Join([]string{
countUp(secondsOf(seenAt(row.Since)), timeCeiling),
row.Cluster,
row.ID,
}, "\x00")
}
return strings.Join([]string{
strconv.Itoa(severityFatal - severityRank(row.Severity)),
countDown(row.Folded, foldCeiling),
countDown(secondsOf(seenAt(row.Since)), timeCeiling),
row.Cluster,
row.ID,
}, "\x00")
}
func countUp(value, ceiling int) string {
if value < 0 {
value = 0
}
if value > ceiling {
value = ceiling
}
width := len(strconv.Itoa(ceiling))
return fmt.Sprintf("%0*d", width, value)
}
func countDown(value, ceiling int) string {
if value < 0 {
value = 0
}
if value > ceiling {
value = ceiling
}
width := len(strconv.Itoa(ceiling))
return fmt.Sprintf("%0*d", width, ceiling-value)
}
func secondsOf(at time.Time) int {
if at.IsZero() {
return 0
}
return int(at.Unix())
}
var (
ErrInvalidCursor = errors.New("that page marker is invalid")
ErrCursorOrder = errors.New("that page marker belongs to a different sort order")
)
func EncodeCursor(key, order string) string {
if key == "" {
return ""
}
return base64.RawURLEncoding.EncodeToString([]byte(order + "\x00" + key))
}
func DecodeCursor(cursor, order string) (string, error) {
if cursor == "" {
return "", nil
}
raw, err := base64.RawURLEncoding.DecodeString(cursor)
if err != nil {
return "", ErrInvalidCursor
}
minted, key, found := strings.Cut(string(raw), "\x00")
if !found || minted == "" || key == "" {
return "", ErrInvalidCursor
}
if minted != order {
return "", ErrCursorOrder
}
return key, nil
}
func Page(rows []api.Issue, after string, limit int, order string) ([]api.Issue, string) {
limit = PageSize(limit)
out := make([]api.Issue, 0, min(limit, len(rows)))
last := ""
for _, row := range rows {
key := issueKey(row, order)
if key <= after {
continue
}
if len(out) == limit {
return out, EncodeCursor(last, order)
}
out = append(out, row)
last = key
}
return out, ""
}
func PageSize(shown int) int {
if shown <= 0 {
return Shown
}
return shown
}