Memoize database functions to reduce disk reads

This commit is contained in:
2026-01-25 14:02:45 +01:00
parent 2a6b903b58
commit 6ce1758672
3 changed files with 86 additions and 39 deletions

117
db.go
View File

@@ -7,6 +7,8 @@ import (
"zkillsusser/models"
utils "git.site.quack-lab.dev/dave/cyutils"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"gorm.io/driver/sqlite"
@@ -64,6 +66,14 @@ type DB interface {
type DBWrapper struct {
ch driver.Conn
db *gorm.DB // For SQLite (EVE static data)
getTypeMemo func(context.Context, int32) (*models.InvType, error)
getGroupMemo func(context.Context, int32) (*models.InvGroup, error)
getCategoryMemo func(context.Context, int32) (*models.InvCategory, error)
getMarketGroupMemo func(context.Context, int32) (*models.InvMarketGroup, error)
getSystemMemo func(context.Context, int32) (*models.MapSolarSystem, error)
getConstellationMemo func(context.Context, int32) (*models.MapConstellation, error)
getRegionMemo func(context.Context, int32) (*models.MapRegion, error)
}
var db *DBWrapper
@@ -87,6 +97,71 @@ func GetDB() (DB, error) {
ch: conn,
db: sdb,
}
getTypeFn := func(ctx context.Context, typeID int32) (*models.InvType, error) {
var t models.InvType
if err := db.db.Where("typeID = ?", typeID).First(&t).Error; err != nil {
return nil, fmt.Errorf("failed to get type %d: %w", typeID, err)
}
return &t, nil
}
getGroupFn := func(ctx context.Context, groupID int32) (*models.InvGroup, error) {
var g models.InvGroup
if err := db.db.Where("groupID = ?", groupID).First(&g).Error; err != nil {
return nil, fmt.Errorf("failed to get group %d: %w", groupID, err)
}
return &g, nil
}
getCategoryFn := func(ctx context.Context, categoryID int32) (*models.InvCategory, error) {
var c models.InvCategory
if err := db.db.Where("categoryID = ?", categoryID).First(&c).Error; err != nil {
return nil, fmt.Errorf("failed to get category %d: %w", categoryID, err)
}
return &c, nil
}
getMarketGroupFn := func(ctx context.Context, marketGroupID int32) (*models.InvMarketGroup, error) {
var mg models.InvMarketGroup
if err := db.db.Where("marketGroupID = ?", marketGroupID).First(&mg).Error; err != nil {
return nil, fmt.Errorf("failed to get market group %d: %w", marketGroupID, err)
}
return &mg, nil
}
getSystemFn := func(ctx context.Context, systemID int32) (*models.MapSolarSystem, error) {
var s models.MapSolarSystem
if err := db.db.Where("solarSystemID = ?", systemID).First(&s).Error; err != nil {
return nil, fmt.Errorf("failed to get solar system %d: %w", systemID, err)
}
return &s, nil
}
getConstellationFn := func(ctx context.Context, constellationID int32) (*models.MapConstellation, error) {
var c models.MapConstellation
if err := db.db.Where("constellationID = ?", constellationID).First(&c).Error; err != nil {
return nil, fmt.Errorf("failed to get constellation %d: %w", constellationID, err)
}
return &c, nil
}
getRegionFn := func(ctx context.Context, regionID int32) (*models.MapRegion, error) {
var r models.MapRegion
if err := db.db.Where("regionID = ?", regionID).First(&r).Error; err != nil {
return nil, fmt.Errorf("failed to get region %d: %w", regionID, err)
}
return &r, nil
}
db.getTypeMemo = utils.Memoized(getTypeFn).(func(context.Context, int32) (*models.InvType, error))
db.getGroupMemo = utils.Memoized(getGroupFn).(func(context.Context, int32) (*models.InvGroup, error))
db.getCategoryMemo = utils.Memoized(getCategoryFn).(func(context.Context, int32) (*models.InvCategory, error))
db.getMarketGroupMemo = utils.Memoized(getMarketGroupFn).(func(context.Context, int32) (*models.InvMarketGroup, error))
db.getSystemMemo = utils.Memoized(getSystemFn).(func(context.Context, int32) (*models.MapSolarSystem, error))
db.getConstellationMemo = utils.Memoized(getConstellationFn).(func(context.Context, int32) (*models.MapConstellation, error))
db.getRegionMemo = utils.Memoized(getRegionFn).(func(context.Context, int32) (*models.MapRegion, error))
err = db.Init()
return db, err
}
@@ -237,57 +312,29 @@ func (db *DBWrapper) GetModuleSlots(moduleIDs []int64) (map[int64]ModuleSlot, er
}
func (db *DBWrapper) GetType(ctx context.Context, typeID int32) (*models.InvType, error) {
var t models.InvType
if err := db.db.Where("typeID = ?", typeID).First(&t).Error; err != nil {
return nil, fmt.Errorf("failed to get type %d: %w", typeID, err)
}
return &t, nil
return db.getTypeMemo(ctx, typeID)
}
func (db *DBWrapper) GetGroup(ctx context.Context, groupID int32) (*models.InvGroup, error) {
var g models.InvGroup
if err := db.db.Where("groupID = ?", groupID).First(&g).Error; err != nil {
return nil, fmt.Errorf("failed to get group %d: %w", groupID, err)
}
return &g, nil
return db.getGroupMemo(ctx, groupID)
}
func (db *DBWrapper) GetCategory(ctx context.Context, categoryID int32) (*models.InvCategory, error) {
var c models.InvCategory
if err := db.db.Where("categoryID = ?", categoryID).First(&c).Error; err != nil {
return nil, fmt.Errorf("failed to get category %d: %w", categoryID, err)
}
return &c, nil
return db.getCategoryMemo(ctx, categoryID)
}
func (db *DBWrapper) GetMarketGroup(ctx context.Context, marketGroupID int32) (*models.InvMarketGroup, error) {
var mg models.InvMarketGroup
if err := db.db.Where("marketGroupID = ?", marketGroupID).First(&mg).Error; err != nil {
return nil, fmt.Errorf("failed to get market group %d: %w", marketGroupID, err)
}
return &mg, nil
return db.getMarketGroupMemo(ctx, marketGroupID)
}
func (db *DBWrapper) GetSolarSystem(ctx context.Context, systemID int32) (*models.MapSolarSystem, error) {
var s models.MapSolarSystem
if err := db.db.Where("solarSystemID = ?", systemID).First(&s).Error; err != nil {
return nil, fmt.Errorf("failed to get solar system %d: %w", systemID, err)
}
return &s, nil
return db.getSystemMemo(ctx, systemID)
}
func (db *DBWrapper) GetConstellation(ctx context.Context, constellationID int32) (*models.MapConstellation, error) {
var c models.MapConstellation
if err := db.db.Where("constellationID = ?", constellationID).First(&c).Error; err != nil {
return nil, fmt.Errorf("failed to get constellation %d: %w", constellationID, err)
}
return &c, nil
return db.getConstellationMemo(ctx, constellationID)
}
func (db *DBWrapper) GetRegion(ctx context.Context, regionID int32) (*models.MapRegion, error) {
var r models.MapRegion
if err := db.db.Where("regionID = ?", regionID).First(&r).Error; err != nil {
return nil, fmt.Errorf("failed to get region %d: %w", regionID, err)
}
return &r, nil
return db.getRegionMemo(ctx, regionID)
}

4
go.mod
View File

@@ -6,8 +6,9 @@ toolchain go1.24.11
require (
git.site.quack-lab.dev/dave/cylogger v1.5.0
git.site.quack-lab.dev/dave/cyutils v1.5.0
git.site.quack-lab.dev/dave/cyutils v1.6.0
github.com/ClickHouse/clickhouse-go/v2 v2.42.0
github.com/joho/godotenv v1.5.1
github.com/nsqio/go-nsq v1.1.0
github.com/stretchr/testify v1.11.1
golang.org/x/sync v0.19.0
@@ -28,7 +29,6 @@ require (
github.com/hexops/valast v1.5.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/paulmach/orb v0.12.0 // indirect

4
go.sum
View File

@@ -1,7 +1,7 @@
git.site.quack-lab.dev/dave/cylogger v1.5.0 h1:9H/eEMD1dqJ9hEudwbszxrzE9lN0P0iCeYOzYRPMWOA=
git.site.quack-lab.dev/dave/cylogger v1.5.0/go.mod h1:wctgZplMvroA4X6p8f4B/LaCKtiBcT1Pp+L14kcS8jk=
git.site.quack-lab.dev/dave/cyutils v1.5.0 h1:U5pojDNoXV4Kj/dlPaGm2COaT4aX6zu88gBF+nTYeJw=
git.site.quack-lab.dev/dave/cyutils v1.5.0/go.mod h1:fBjALu2Cp2u2bDr+E4zbGVMBeIgFzROg+4TCcTNAiQU=
git.site.quack-lab.dev/dave/cyutils v1.6.0 h1:l+2Xv3c10SUAW+lOkrW5qt/Nf9+ocbkm6J4h8xP8p1Q=
git.site.quack-lab.dev/dave/cyutils v1.6.0/go.mod h1:fBjALu2Cp2u2bDr+E4zbGVMBeIgFzROg+4TCcTNAiQU=
github.com/ClickHouse/ch-go v0.69.0 h1:nO0OJkpxOlN/eaXFj0KzjTz5p7vwP1/y3GN4qc5z/iM=
github.com/ClickHouse/ch-go v0.69.0/go.mod h1:9XeZpSAT4S0kVjOpaJ5186b7PY/NH/hhF8R6u0WIjwg=
github.com/ClickHouse/clickhouse-go/v2 v2.42.0 h1:MdujEfIrpXesQUH0k0AnuVtJQXk6RZmxEhsKUCcv5xk=