From 6ce17586729cadff4e58bf10c161c9eb600778db Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sun, 25 Jan 2026 14:02:45 +0100 Subject: [PATCH] Memoize database functions to reduce disk reads --- db.go | 117 ++++++++++++++++++++++++++++++++++++++++----------------- go.mod | 4 +- go.sum | 4 +- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/db.go b/db.go index 2ff4402..1abb023 100644 --- a/db.go +++ b/db.go @@ -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) } diff --git a/go.mod b/go.mod index ef00696..fdc8d19 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 5d1e231..c15be8f 100644 --- a/go.sum +++ b/go.sum @@ -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=