Actually finish 🤞 DB-/ID-related refactors

This commit is contained in:
Amolith 2024-02-23 21:16:50 -05:00
parent b6db773ee3
commit dd7551fd49
Signed by: Amolith
SSH Key Fingerprint: SHA256:JBKEeoO/72Fz03rtlzeO49PATFT2maMancH3opcT0h0
4 changed files with 74 additions and 65 deletions

View File

@ -22,9 +22,9 @@ func DeleteProject(db *sql.DB, mu *sync.Mutex, id string) error {
} }
// GetProject returns a project from the database // GetProject returns a project from the database
func GetProject(db *sql.DB, url string) (map[string]string, error) { func GetProject(db *sql.DB, id string) (map[string]string, error) {
var id, name, forge, version string var name, forge, url, version string
err := db.QueryRow("SELECT id, name, forge, version FROM projects WHERE url = ?", url).Scan(&id, &name, &forge, &version) err := db.QueryRow("SELECT name, forge, url, version FROM projects WHERE id = ?", id).Scan(&name, &forge, &url, &version)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -9,7 +9,7 @@ import (
"sync" "sync"
) )
// UpsertRelease adds or updates a release for a project with a given URL in the // UpsertRelease adds or updates a release for a project with a given ID in the
// database // database
func UpsertRelease(db *sql.DB, mu *sync.Mutex, id, projectID, url, tag, content, date string) error { func UpsertRelease(db *sql.DB, mu *sync.Mutex, id, projectID, url, tag, content, date string) error {
mu.Lock() mu.Lock()
@ -48,11 +48,12 @@ func GetReleases(db *sql.DB, projectID string) ([]map[string]string, error) {
return nil, err return nil, err
} }
releases = append(releases, map[string]string{ releases = append(releases, map[string]string{
"id": id, "id": id,
"url": url, "project_id": projectID,
"tag": tag, "url": url,
"content": content, "tag": tag,
"date": date, "content": content,
"date": date,
}) })
} }
return releases, nil return releases, nil

View File

@ -7,6 +7,7 @@ package project
import ( import (
"crypto/sha256" "crypto/sha256"
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"log" "log"
"sort" "sort"
@ -41,22 +42,33 @@ type Release struct {
// GetReleases returns a list of all releases for a project from the database // GetReleases returns a list of all releases for a project from the database
func GetReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error) { func GetReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error) {
proj.ID = GenProjectID(proj.URL, proj.Name, proj.Forge)
ret, err := db.GetReleases(dbConn, proj.ID) ret, err := db.GetReleases(dbConn, proj.ID)
if err != nil { if err != nil {
return proj, err return proj, err
} }
if len(ret) == 0 { if len(ret) == 0 {
return fetchReleases(dbConn, mu, proj) proj, err = fetchReleases(dbConn, mu, proj)
if err != nil {
return proj, err
}
err = upsertReleases(dbConn, mu, proj.ID, proj.Releases)
if err != nil {
return proj, err
}
return proj, nil
} }
for _, row := range ret { for _, row := range ret {
proj.Releases = append(proj.Releases, Release{ proj.Releases = append(proj.Releases, Release{
ID: row["id"], ID: row["id"],
Tag: row["tag"], ProjectID: proj.ID,
Content: row["content"], Tag: row["tag"],
URL: row["release_url"], Content: row["content"],
Date: time.Time{}, URL: row["release_url"],
Date: time.Time{},
}) })
} }
proj.Releases = SortReleases(proj.Releases) proj.Releases = SortReleases(proj.Releases)
@ -81,7 +93,7 @@ func fetchReleases(dbConn *sql.DB, mu *sync.Mutex, p Project) (Project, error) {
URL: release.URL, URL: release.URL,
Date: release.Date, Date: release.Date,
}) })
err = upsertRelease(dbConn, mu, p.URL, p.Releases) err = upsertReleases(dbConn, mu, p.ID, p.Releases)
if err != nil { if err != nil {
log.Printf("Error upserting release: %v", err) log.Printf("Error upserting release: %v", err)
return p, err return p, err
@ -100,7 +112,7 @@ func fetchReleases(dbConn *sql.DB, mu *sync.Mutex, p Project) (Project, error) {
URL: release.URL, URL: release.URL,
Date: release.Date, Date: release.Date,
}) })
err = upsertRelease(dbConn, mu, p.URL, p.Releases) err = upsertReleases(dbConn, mu, p.ID, p.Releases)
if err != nil { if err != nil {
log.Printf("Error upserting release: %v", err) log.Printf("Error upserting release: %v", err)
return p, err return p, err
@ -118,12 +130,11 @@ func SortReleases(releases []Release) []Release {
return releases return releases
} }
// upsertRelease updates or inserts a release in the database // upsertReleases updates or inserts a release in the database
func upsertRelease(dbConn *sql.DB, mu *sync.Mutex, url string, releases []Release) error { func upsertReleases(dbConn *sql.DB, mu *sync.Mutex, projID string, releases []Release) error {
for _, release := range releases { for _, release := range releases {
date := release.Date.Format("2006-01-02 15:04:05") date := release.Date.Format("2006-01-02 15:04:05")
id := GenReleaseID(url, release.URL, release.Tag) err := db.UpsertRelease(dbConn, mu, release.ID, projID, release.URL, release.Tag, release.Content, date)
err := db.UpsertRelease(dbConn, mu, id, url, release.URL, release.Tag, release.Content, date)
if err != nil { if err != nil {
log.Printf("Error upserting release: %v", err) log.Printf("Error upserting release: %v", err)
return err return err
@ -185,7 +196,7 @@ func RefreshLoop(dbConn *sql.DB, mu *sync.Mutex, interval int, manualRefresh, re
return strings.ToLower(projectsList[i].Name) < strings.ToLower(projectsList[j].Name) return strings.ToLower(projectsList[i].Name) < strings.ToLower(projectsList[j].Name)
}) })
for i := range projectsList { for i := range projectsList {
err = upsertRelease(dbConn, mu, projectsList[i].URL, projectsList[i].Releases) err = upsertReleases(dbConn, mu, projectsList[i].ID, projectsList[i].Releases)
if err != nil { if err != nil {
fmt.Println("Error upserting release:", err) fmt.Println("Error upserting release:", err)
continue continue
@ -212,24 +223,26 @@ func RefreshLoop(dbConn *sql.DB, mu *sync.Mutex, interval int, manualRefresh, re
} }
// GetProject returns a project from the database // GetProject returns a project from the database
func GetProject(dbConn *sql.DB, id string) (Project, error) { func GetProject(dbConn *sql.DB, proj Project) (Project, error) {
projectDB, err := db.GetProject(dbConn, id) projectDB, err := db.GetProject(dbConn, proj.ID)
if err != nil { if err != nil && errors.Is(err, sql.ErrNoRows) {
return Project{}, err return proj, nil
} else if err != nil {
return proj, err
} }
p := Project{ p := Project{
ID: projectDB["id"], ID: proj.ID,
URL: projectDB["url"], URL: proj.URL,
Name: projectDB["name"], Name: proj.Name,
Forge: projectDB["forge"], Forge: proj.Forge,
Running: projectDB["version"], Running: projectDB["version"],
} }
return p, err return p, err
} }
// GetProjectWithReleases returns a single project from the database along with its releases // GetProjectWithReleases returns a single project from the database along with its releases
func GetProjectWithReleases(dbConn *sql.DB, mu *sync.Mutex, id string) (Project, error) { func GetProjectWithReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error) {
project, err := GetProject(dbConn, id) project, err := GetProject(dbConn, proj)
if err != nil { if err != nil {
return Project{}, err return Project{}, err
} }

View File

@ -80,7 +80,34 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
proj, err := project.GetProject(h.DbConn, submittedURL) forge := bmStrict.Sanitize(params.Get("forge"))
if forge == "" {
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("No forge provided"))
if err != nil {
fmt.Println(err)
}
return
}
name := bmStrict.Sanitize(params.Get("name"))
if name == "" {
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("No name provided"))
if err != nil {
fmt.Println(err)
}
return
}
proj := project.Project{
ID: project.GenProjectID(submittedURL, name, forge),
URL: submittedURL,
Name: name,
Forge: forge,
}
proj, err := project.GetProject(h.DbConn, proj)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte(fmt.Sprintf("Error getting project: %s", err))) _, err := w.Write([]byte(fmt.Sprintf("Error getting project: %s", err)))
@ -90,38 +117,6 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
if proj.Running == "" {
forge := bmStrict.Sanitize(params.Get("forge"))
if forge == "" {
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("No forge provided"))
if err != nil {
fmt.Println(err)
}
return
}
name := bmStrict.Sanitize(params.Get("name"))
if name == "" {
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("No name provided"))
if err != nil {
fmt.Println(err)
}
return
}
proj = project.Project{
URL: submittedURL,
Name: name,
Forge: forge,
}
proj.URL = strings.TrimSuffix(proj.URL, ".git")
}
proj.ID = project.GenProjectID(proj.URL, proj.Name, proj.Forge)
proj, err = project.GetReleases(h.DbConn, h.Mu, proj) proj, err = project.GetReleases(h.DbConn, h.Mu, proj)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)