Implemented easer feature to reduce the DB load

This commit is contained in:
ktsivkov 2023-03-20 16:03:09 +01:00
parent 970341a12a
commit a688acb023
3 changed files with 81 additions and 8 deletions

View File

@ -9,7 +9,6 @@ import (
"reflect"
"sort"
"strings"
"time"
)
func Query(db *gorm.DB) {
@ -17,7 +16,6 @@ func Query(db *gorm.DB) {
BuildQuerySQL(db)
var _query = func(db *gorm.DB) {
time.Sleep(5 * time.Second)
if !db.DryRun && db.Error == nil {
rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
if err != nil {

10
gorm.go
View File

@ -58,10 +58,10 @@ type Config struct {
Plugins map[string]Plugin
// Ease database load by grouping identical queries
Ease bool
EaseQueue *sync.Map
callbacks *callbacks
cacheStore *sync.Map
easeQueue *sync.Map
}
// Apply update config to new config
@ -170,8 +170,8 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
config.cacheStore = &sync.Map{}
}
if config.Ease && config.easeQueue == nil {
config.easeQueue = &sync.Map{}
if config.Ease && config.EaseQueue == nil {
config.EaseQueue = &sync.Map{}
}
db = &DB{Config: config, clone: 1}
@ -501,13 +501,13 @@ func (db *DB) Ease(cb func(*DB)) *DB {
}
eq.wg.Add(1)
var runner, ok = db.easeQueue.LoadOrStore(hash, eq)
var runner, ok = db.EaseQueue.LoadOrStore(hash, eq)
et := runner.(*easedTask)
if !ok {
cb(db)
et.wg.Done()
db.easeQueue.Delete(hash)
db.EaseQueue.Delete(hash)
return db
}

75
tests/easer_test.go Normal file
View File

@ -0,0 +1,75 @@
package tests_test
import (
"gorm.io/gorm"
"sync"
"testing"
"time"
)
func TestEaser(t *testing.T) {
t.Run("once", func(t *testing.T) {
db1 := DB.Unscoped()
db1.Config.EaseQueue = &sync.Map{}
wg := &sync.WaitGroup{}
wg.Add(2)
incr := 0
testQuery := func(d *gorm.DB) {
time.Sleep(time.Second)
incr++
}
go func() {
db1.Ease(testQuery)
wg.Done()
}()
go func() {
time.Sleep(500 * time.Millisecond)
db1.Ease(testQuery)
wg.Done()
}()
wg.Wait()
if incr != 1 {
t.Error("easer had to run the query only once")
}
})
t.Run("twice", func(t *testing.T) {
db1 := DB.Unscoped()
db1.Config.EaseQueue = &sync.Map{}
wg := &sync.WaitGroup{}
wg.Add(2)
incr := 0
testQuery := func(d *gorm.DB) {
time.Sleep(time.Second)
incr++
}
go func() {
db1.Statement.SQL.WriteString("q1")
db1.Ease(testQuery)
wg.Done()
}()
go func() {
time.Sleep(500 * time.Millisecond)
db1.Statement.SQL.WriteString("q2")
db1.Ease(testQuery)
wg.Done()
}()
wg.Wait()
if incr != 2 {
t.Error("easer had to run two separate queries")
}
})
}