Migrate db logic to db where it belongs

This commit is contained in:
2026-01-05 22:45:14 +01:00
parent f4ee303dcc
commit ae67648ee4
2 changed files with 155 additions and 105 deletions

172
api.go
View File

@@ -10,8 +10,6 @@ import (
"sync"
"time"
"zkillsusser/models"
logger "git.site.quack-lab.dev/dave/cylogger"
)
@@ -219,73 +217,64 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
results := []APISearchResult{}
searchPattern := "%" + strings.ToLower(query) + "%"
flog.Debug("Search pattern: %q", searchPattern)
flog.Debug("Searching ships")
var ships []models.InvType
db.DB().Table("invTypes").
Joins("INNER JOIN invGroups ON invTypes.groupID = invGroups.groupID").
Where("LOWER(invTypes.\"typeName\") LIKE ? AND invGroups.categoryID IN (6)", searchPattern).
Limit(10).
Find(&ships)
flog.Info("Found %d ships", len(ships))
flog.Trace("Ships: %+v", ships)
for _, ship := range ships {
results = append(results, APISearchResult{
ID: int64(ship.TypeID),
Name: ship.TypeName,
Type: "ship",
})
ships, err := db.SearchShips(query, 10)
if err != nil {
flog.Error("Failed to search ships: %v", err)
} else {
flog.Info("Found %d ships", len(ships))
for _, ship := range ships {
results = append(results, APISearchResult{
ID: int64(ship.TypeID),
Name: ship.TypeName,
Type: "ship",
})
}
}
flog.Debug("Searching systems")
var systems []models.MapSolarSystem
db.DB().Table("mapSolarSystems").
Where("LOWER(\"solarSystemName\") LIKE ?", searchPattern).
Limit(10).
Find(&systems)
flog.Info("Found %d systems", len(systems))
flog.Trace("Systems: %+v", systems)
for _, system := range systems {
results = append(results, APISearchResult{
ID: int64(system.SolarSystemID),
Name: system.SolarSystemName,
Type: "system",
})
systems, err := db.SearchSystems(query, 10)
if err != nil {
flog.Error("Failed to search systems: %v", err)
} else {
flog.Info("Found %d systems", len(systems))
for _, system := range systems {
results = append(results, APISearchResult{
ID: int64(system.SolarSystemID),
Name: system.SolarSystemName,
Type: "system",
})
}
}
flog.Debug("Searching modules")
var modules []models.InvType
db.DB().Table("invTypes").
Joins("INNER JOIN invGroups ON invTypes.groupID = invGroups.groupID").
Where("LOWER(invTypes.\"typeName\") LIKE ? AND invGroups.categoryID IN (7, 66)", searchPattern).
Limit(10).
Find(&modules)
flog.Info("Found %d modules", len(modules))
flog.Trace("Modules: %+v", modules)
for _, module := range modules {
results = append(results, APISearchResult{
ID: int64(module.TypeID),
Name: module.TypeName,
Type: "module",
})
modules, err := db.SearchModules(query, 10)
if err != nil {
flog.Error("Failed to search modules: %v", err)
} else {
flog.Info("Found %d modules", len(modules))
for _, module := range modules {
results = append(results, APISearchResult{
ID: int64(module.TypeID),
Name: module.TypeName,
Type: "module",
})
}
}
flog.Debug("Searching groups")
var groups []models.InvGroup
db.DB().Table("invGroups").
Where("LOWER(\"groupName\") LIKE ?", searchPattern).
Limit(10).
Find(&groups)
flog.Info("Found %d groups", len(groups))
flog.Trace("Groups: %+v", groups)
for _, group := range groups {
results = append(results, APISearchResult{
ID: int64(group.GroupID),
Name: group.GroupName,
Type: "group",
})
groups, err := db.SearchGroups(query, 10)
if err != nil {
flog.Error("Failed to search groups: %v", err)
} else {
flog.Info("Found %d groups", len(groups))
for _, group := range groups {
results = append(results, APISearchResult{
ID: int64(group.GroupID),
Name: group.GroupName,
Type: "group",
})
}
}
flog.Info("Total search results: %d", len(results))
@@ -332,7 +321,6 @@ func handleItemNames(w http.ResponseWriter, r *http.Request) {
ids = append(ids, int32(id))
}
flog.Info("Parsed %d valid IDs from %d strings", len(ids), len(idStrs))
flog.Dump("IDs", ids)
if len(ids) == 0 {
flog.Info("No valid IDs, returning empty map")
@@ -349,30 +337,12 @@ func handleItemNames(w http.ResponseWriter, r *http.Request) {
}
flog.Trace("Database connection obtained")
flog.Debug("Querying invTypes for %d IDs", len(ids))
var items []models.InvType
db.DB().Table("invTypes").
Where("typeID IN ?", ids).
Find(&items)
flog.Info("Found %d items in invTypes", len(items))
flog.Trace("Items: %+v", items)
names := make(APIItemNames)
for _, item := range items {
names[strconv.FormatInt(int64(item.TypeID), 10)] = item.TypeName
}
flog.Debug("Added %d item names", len(names))
flog.Debug("Querying mapSolarSystems for %d IDs", len(ids))
systemIDs := ids
var systems []models.MapSolarSystem
db.DB().Table("mapSolarSystems").
Where("\"solarSystemID\" IN ?", systemIDs).
Find(&systems)
flog.Info("Found %d systems in mapSolarSystems", len(systems))
flog.Trace("Systems: %+v", systems)
for _, system := range systems {
names[strconv.FormatInt(int64(system.SolarSystemID), 10)] = system.SolarSystemName
flog.Debug("Getting item names for %d IDs", len(ids))
names, err := db.GetItemNames(ids)
if err != nil {
flog.Error("Failed to get item names: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
flog.Info("Total names: %d", len(names))
flog.Dump("Names", names)
@@ -423,26 +393,22 @@ func handleItemGroup(w http.ResponseWriter, r *http.Request) {
}
flog.Trace("Database connection obtained")
flog.Debug("Querying invTypes for typeID: %d", itemID)
var item models.InvType
result := db.DB().Table("invTypes").
Where("typeID = ?", int32(itemID)).
First(&item)
if result.Error != nil && strings.Contains(result.Error.Error(), "record not found") {
flog.Info("Item not found: typeID %d", itemID)
http.Error(w, "Item not found", http.StatusNotFound)
return
}
if result.Error != nil {
flog.Error("Failed to query item: %v", result.Error)
flog.Debug("Getting group for itemID: %d", itemID)
groupID, err := db.GetItemGroup(itemID)
if err != nil {
if strings.Contains(err.Error(), "record not found") {
flog.Info("Item not found: typeID %d", itemID)
http.Error(w, "Item not found", http.StatusNotFound)
return
}
flog.Error("Failed to get item group: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
flog.Info("Found item: typeID %d, groupID %d", item.TypeID, item.GroupID)
flog.Dump("Item", item)
flog.Info("Found groupID %d for itemID %d", groupID, itemID)
groupInfo := APIGroupInfo{
GroupID: int64(item.GroupID),
GroupID: groupID,
}
flog.Dump("Group Info", groupInfo)
@@ -605,10 +571,10 @@ func StartAPIServer(port string) {
flog.Debug("Registered routes:")
flog.Debug(" POST /api/statistics")
flog.Debug(" GET /api/search")
flog.Debug(" GET /api/items/names")
flog.Debug(" GET /api/items/{id}/group")
flog.Debug(" GET /api/images/{typeId}/{size}")
flog.Debug(" GET /api/search")
flog.Debug(" GET /api/items/names")
flog.Debug(" GET /api/items/{id}/group")
flog.Debug(" GET /api/images/{typeId}/{size}")
flog.Info("Starting API server on port %s", port)
flog.Trace("Listening on :%s", port)

88
db.go
View File

@@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"strconv"
"strings"
"time"
@@ -56,13 +57,17 @@ type ModuleStats struct {
}
type DB interface {
DB() *gorm.DB
Raw(sql string, args ...any) *gorm.DB
SaveKillmails(killmails []Killmail) error
InitTables() error
QueryFits(params QueryParams) (*FitStatistics, error)
GetCachedStatistics(cacheKey string) ([]byte, bool)
CacheStatistics(cacheKey string, data []byte) error
SearchShips(query string, limit int) ([]models.InvType, error)
SearchSystems(query string, limit int) ([]models.MapSolarSystem, error)
SearchModules(query string, limit int) ([]models.InvType, error)
SearchGroups(query string, limit int) ([]models.InvGroup, error)
GetItemNames(ids []int32) (map[string]string, error)
GetItemGroup(itemID int64) (int64, error)
}
type DBWrapper struct {
@@ -576,6 +581,85 @@ func (db *DBWrapper) CacheStatistics(cacheKey string, data []byte) error {
}).Error
}
func (db *DBWrapper) SearchShips(query string, limit int) ([]models.InvType, error) {
var ships []models.InvType
searchPattern := "%" + strings.ToLower(query) + "%"
err := db.gormDB.Table("invTypes").
Joins("INNER JOIN invGroups ON invTypes.groupID = invGroups.groupID").
Where("LOWER(invTypes.\"typeName\") LIKE ? AND invGroups.categoryID IN (6)", searchPattern).
Limit(limit).
Find(&ships).Error
return ships, err
}
func (db *DBWrapper) SearchSystems(query string, limit int) ([]models.MapSolarSystem, error) {
var systems []models.MapSolarSystem
searchPattern := "%" + strings.ToLower(query) + "%"
err := db.gormDB.Table("mapSolarSystems").
Where("LOWER(\"solarSystemName\") LIKE ?", searchPattern).
Limit(limit).
Find(&systems).Error
return systems, err
}
func (db *DBWrapper) SearchModules(query string, limit int) ([]models.InvType, error) {
var modules []models.InvType
searchPattern := "%" + strings.ToLower(query) + "%"
err := db.gormDB.Table("invTypes").
Joins("INNER JOIN invGroups ON invTypes.groupID = invGroups.groupID").
Where("LOWER(invTypes.\"typeName\") LIKE ? AND invGroups.categoryID IN (7, 66)", searchPattern).
Limit(limit).
Find(&modules).Error
return modules, err
}
func (db *DBWrapper) SearchGroups(query string, limit int) ([]models.InvGroup, error) {
var groups []models.InvGroup
searchPattern := "%" + strings.ToLower(query) + "%"
err := db.gormDB.Table("invGroups").
Where("LOWER(\"groupName\") LIKE ?", searchPattern).
Limit(limit).
Find(&groups).Error
return groups, err
}
func (db *DBWrapper) GetItemNames(ids []int32) (map[string]string, error) {
names := make(map[string]string)
var items []models.InvType
if err := db.gormDB.Table("invTypes").
Where("typeID IN ?", ids).
Find(&items).Error; err != nil {
return nil, err
}
for _, item := range items {
names[strconv.FormatInt(int64(item.TypeID), 10)] = item.TypeName
}
var systems []models.MapSolarSystem
if err := db.gormDB.Table("mapSolarSystems").
Where("\"solarSystemID\" IN ?", ids).
Find(&systems).Error; err != nil {
return nil, err
}
for _, system := range systems {
names[strconv.FormatInt(int64(system.SolarSystemID), 10)] = system.SolarSystemName
}
return names, nil
}
func (db *DBWrapper) GetItemGroup(itemID int64) (int64, error) {
var item models.InvType
err := db.gormDB.Table("invTypes").
Where("typeID = ?", int32(itemID)).
First(&item).Error
if err != nil {
return 0, err
}
return int64(item.GroupID), nil
}
func deduplicateInt64(slice []int64) []int64 {
seen := make(map[int64]bool)
result := make([]int64, 0, len(slice))