package main import ( "github.com/c2h5oh/datasize" "github.com/go-chi/render" log "github.com/sirupsen/logrus" "net/http" "os" "somegit.dev/ALHP/ALHP.GO/ent" "somegit.dev/ALHP/ALHP.GO/ent/dbpackage" "somegit.dev/ALHP/ALHP.GO/ent/predicate" "strconv" "strings" "time" ) type StatsResponse struct { Failed int `json:"failed"` Skipped int `json:"skipped"` Latest int `json:"latest"` Queued int `json:"queued"` Building int `json:"building"` LastMirrorTimestamp *int64 `json:"last_mirror_timestamp,omitempty"` LTO *struct { Enabled int `json:"enabled"` Disabled int `json:"disabled"` Unknown int `json:"unknown"` } `json:"lto"` } type ThinPackage struct { Pkgbase string `json:"pkgbase"` Repo string `json:"repo"` SplitPackages []string `json:"split_packages"` Status dbpackage.Status `json:"status"` SkipReason *string `json:"skip_reason,omitempty"` LTO dbpackage.Lto `json:"lto"` DebugSymbols dbpackage.DebugSymbols `json:"debug_symbols"` ArchVersion string `json:"arch_version"` RepoVersion string `json:"repo_version"` BuildDate *string `json:"build_date,omitempty"` PeakMem *string `json:"peak_mem,omitempty"` } type PackageResponse struct { Packages []*ThinPackage `json:"packages"` Total int `json:"total"` Offset int `json:"offset"` Limit int `json:"limit"` } func GetStats(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var v []struct { Status dbpackage.Status `json:"status"` Count int `json:"count"` } db.DBPackage.Query().GroupBy(dbpackage.FieldStatus).Aggregate(ent.Count()).ScanX(ctx, &v) resp := new(StatsResponse) resp.LTO = new(struct { Enabled int `json:"enabled"` Disabled int `json:"disabled"` Unknown int `json:"unknown"` }) for _, c := range v { switch c.Status { case dbpackage.StatusFailed: resp.Failed = c.Count case dbpackage.StatusSkipped: resp.Skipped = c.Count case dbpackage.StatusLatest: resp.Latest = c.Count case dbpackage.StatusQueued: resp.Queued = c.Count case dbpackage.StatusBuilding: resp.Building = c.Count } } var v2 []struct { Status dbpackage.Lto `json:"lto"` Count int `json:"count"` } db.DBPackage.Query().Where(dbpackage.StatusNEQ(dbpackage.StatusSkipped)). GroupBy(dbpackage.FieldLto).Aggregate(ent.Count()).ScanX(ctx, &v2) for _, c := range v2 { switch c.Status { case dbpackage.LtoUnknown: resp.LTO.Unknown = c.Count case dbpackage.LtoDisabled, dbpackage.LtoAutoDisabled: resp.LTO.Disabled += c.Count case dbpackage.LtoEnabled: resp.LTO.Enabled = c.Count } } if os.Getenv("ALHP_TIMESTAMP_PATH") != "" { tsFile, err := os.ReadFile(os.Getenv("ALHP_TIMESTAMP_PATH")) if err != nil { log.Warningf("error reading timestamp file: %v", err) } else { ts, err := strconv.ParseInt(string(tsFile), 10, 64) if err != nil { log.Warningf("error parsing timestamp file: %v", err) } else { resp.LastMirrorTimestamp = &ts } } } render.Status(r, http.StatusOK) render.JSON(w, r, resp) } func GetPackages(w http.ResponseWriter, r *http.Request) { ctx := r.Context() pkgbase := r.URL.Query().Get("pkgbase") status := r.URL.Query()["status"] repo := r.URL.Query().Get("repo") offset, err := strconv.Atoi(r.URL.Query().Get("offset")) if err != nil { log.Debugf("error parsing page: %v", err) w.WriteHeader(http.StatusBadRequest) return } limit, err := strconv.Atoi(r.URL.Query().Get("limit")) if err != nil { log.Debugf("error parsing page: %v", err) w.WriteHeader(http.StatusBadRequest) return } var constraints []predicate.DBPackage if pkgbase != "" { if r.URL.Query().Has("exact") { constraints = append(constraints, dbpackage.PkgbaseEQ(pkgbase)) } else { constraints = append(constraints, dbpackage.PkgbaseContains(pkgbase)) } } if len(status) > 0 { constraints = append(constraints, dbpackage.StatusIn(func(status []string) (result []dbpackage.Status) { for _, s := range status { result = append(result, dbpackage.Status(s)) } return result }(status)...)) } if repo != "" { before, after, found := strings.Cut(repo, "-") if found { constraints = append(constraints, dbpackage.And(dbpackage.MarchEQ(after), dbpackage.RepositoryEQ(dbpackage.Repository(before)))) } } nPkgs, err := db.DBPackage.Query().Where(constraints...).Count(ctx) if err != nil { log.Warningf("error getting package count from db: %v", err) render.Status(r, http.StatusInternalServerError) return } if nPkgs == 0 { w.WriteHeader(http.StatusNotFound) return } rPackages, err := db.DBPackage.Query().Where(constraints...).Limit(limit).Offset(offset).All(ctx) if err != nil { log.Warningf("error getting packages from db: %v", err) render.Status(r, http.StatusInternalServerError) return } resp := new(PackageResponse) for _, mPkg := range rPackages { nPkg := &ThinPackage{ Pkgbase: mPkg.Pkgbase, Repo: mPkg.Repository.String() + "-" + mPkg.March, SplitPackages: mPkg.Packages, Status: mPkg.Status, LTO: mPkg.Lto, DebugSymbols: mPkg.DebugSymbols, ArchVersion: mPkg.Version, RepoVersion: mPkg.RepoVersion, } if mPkg.SkipReason != "" { nPkg.SkipReason = &mPkg.SkipReason } if !mPkg.BuildTimeStart.IsZero() { formattedBuildDate := mPkg.BuildTimeStart.UTC().Format(time.RFC1123) nPkg.BuildDate = &formattedBuildDate } if mPkg.MaxRss != nil { hrSize := (datasize.ByteSize(*mPkg.MaxRss) * datasize.KB).HumanReadable() nPkg.PeakMem = &hrSize } resp.Packages = append(resp.Packages, nPkg) } resp.Offset = offset resp.Limit = limit resp.Total = nPkgs render.Status(r, http.StatusOK) render.JSON(w, r, resp) }