Implemented easer feature to reduce the DB load
This commit is contained in:
parent
970341a12a
commit
a688acb023
@ -9,7 +9,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Query(db *gorm.DB) {
|
func Query(db *gorm.DB) {
|
||||||
@ -17,7 +16,6 @@ func Query(db *gorm.DB) {
|
|||||||
BuildQuerySQL(db)
|
BuildQuerySQL(db)
|
||||||
|
|
||||||
var _query = func(db *gorm.DB) {
|
var _query = func(db *gorm.DB) {
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
if !db.DryRun && db.Error == nil {
|
if !db.DryRun && db.Error == nil {
|
||||||
rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
|
rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
10
gorm.go
10
gorm.go
@ -58,10 +58,10 @@ type Config struct {
|
|||||||
Plugins map[string]Plugin
|
Plugins map[string]Plugin
|
||||||
// Ease database load by grouping identical queries
|
// Ease database load by grouping identical queries
|
||||||
Ease bool
|
Ease bool
|
||||||
|
EaseQueue *sync.Map
|
||||||
|
|
||||||
callbacks *callbacks
|
callbacks *callbacks
|
||||||
cacheStore *sync.Map
|
cacheStore *sync.Map
|
||||||
easeQueue *sync.Map
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply update config to new config
|
// Apply update config to new config
|
||||||
@ -170,8 +170,8 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
|
|||||||
config.cacheStore = &sync.Map{}
|
config.cacheStore = &sync.Map{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Ease && config.easeQueue == nil {
|
if config.Ease && config.EaseQueue == nil {
|
||||||
config.easeQueue = &sync.Map{}
|
config.EaseQueue = &sync.Map{}
|
||||||
}
|
}
|
||||||
|
|
||||||
db = &DB{Config: config, clone: 1}
|
db = &DB{Config: config, clone: 1}
|
||||||
@ -501,13 +501,13 @@ func (db *DB) Ease(cb func(*DB)) *DB {
|
|||||||
}
|
}
|
||||||
eq.wg.Add(1)
|
eq.wg.Add(1)
|
||||||
|
|
||||||
var runner, ok = db.easeQueue.LoadOrStore(hash, eq)
|
var runner, ok = db.EaseQueue.LoadOrStore(hash, eq)
|
||||||
et := runner.(*easedTask)
|
et := runner.(*easedTask)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
cb(db)
|
cb(db)
|
||||||
et.wg.Done()
|
et.wg.Done()
|
||||||
db.easeQueue.Delete(hash)
|
db.EaseQueue.Delete(hash)
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
tests/easer_test.go
Normal file
75
tests/easer_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user