code optimize

This commit is contained in:
xing 2023-12-03 22:42:44 +08:00
parent 137b2a9738
commit ac29cf2448
10 changed files with 94 additions and 67 deletions

View File

@ -134,7 +134,7 @@ func (i *IndexHandle) BuildIndexData(parm *IndexParams) (err error) {
} }
i.Posts = posts i.Posts = posts
i.TotalRows = totalRows i.TotalRows = totalRows
i.ginH["totalPage"] = number.CalTotalPage(totalRows, i.Param.PageSize) i.ginH["totalPage"] = number.DivideCeil(totalRows, i.Param.PageSize)
return return
} }

View File

@ -169,7 +169,7 @@ func parseArgs(args ...any) (string, func() time.Duration) {
} }
func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapBatchFn[K, V], fn cache.MapSingleFn[K, V], args ...any) *cache.MapCache[K, V] { func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapBatchFn[K, V], fn cache.MapSingleFn[K, V], args ...any) *cache.MapCache[K, V] {
inc := helper.ParseArgs(cache.IncreaseUpdate[K, V]{}, args...) inc := helper.ParseArgs((*cache.IncreaseUpdate[K, V])(nil), args...)
m := cache.NewMapCache[K, V](data, fn, batchFn, inc) m := cache.NewMapCache[K, V](data, fn, batchFn, inc)
FlushPush(m) FlushPush(m)
ClearPush(m) ClearPush(m)
@ -219,7 +219,7 @@ func ClearExpired() {
} }
func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] { func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] {
inc := helper.ParseArgs(cache.IncreaseUpdateVar[T]{}, a...) inc := helper.ParseArgs((*cache.IncreaseUpdateVar[T])(nil), a...)
ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...) ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...)
v := cache.NewVarCache(c, fn, inc, ref) v := cache.NewVarCache(c, fn, inc, ref)
FlushPush(v) FlushPush(v)

79
cache/map.go vendored
View File

@ -18,7 +18,7 @@ type MapCache[K comparable, V any] struct {
batchCacheFn MapBatchFn[K, V] batchCacheFn MapBatchFn[K, V]
getCacheBatch func(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) getCacheBatch func(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error)
getCacheBatchToMap func(c context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error) getCacheBatchToMap func(c context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error)
increaseUpdate IncreaseUpdate[K, V] increaseUpdate *IncreaseUpdate[K, V]
refresh Refresh[K, V] refresh Refresh[K, V]
} }
type IncreaseUpdate[K comparable, V any] struct { type IncreaseUpdate[K comparable, V any] struct {
@ -26,16 +26,16 @@ type IncreaseUpdate[K comparable, V any] struct {
Fn IncreaseFn[K, V] Fn IncreaseFn[K, V]
} }
func NewIncreaseUpdate[K comparable, V any](name string, fn IncreaseFn[K, V], cycleTime time.Duration, tFn func() time.Duration) IncreaseUpdate[K, V] { func NewIncreaseUpdate[K comparable, V any](name string, fn IncreaseFn[K, V], cycleTime time.Duration, tFn func() time.Duration) *IncreaseUpdate[K, V] {
tFn = reload.FnVal(name, cycleTime, tFn) tFn = reload.FnVal(name, cycleTime, tFn)
return IncreaseUpdate[K, V]{CycleTime: tFn, Fn: fn} return &IncreaseUpdate[K, V]{CycleTime: tFn, Fn: fn}
} }
type MapSingleFn[K, V any] func(context.Context, K, ...any) (V, error) type MapSingleFn[K, V any] func(context.Context, K, ...any) (V, error)
type MapBatchFn[K comparable, V any] func(context.Context, []K, ...any) (map[K]V, error) type MapBatchFn[K comparable, V any] func(context.Context, []K, ...any) (map[K]V, error)
type IncreaseFn[K comparable, V any] func(c context.Context, currentData V, k K, t time.Time, a ...any) (data V, save bool, refresh bool, err error) type IncreaseFn[K comparable, V any] func(c context.Context, currentData V, k K, t time.Time, a ...any) (data V, save bool, refresh bool, err error)
func NewMapCache[K comparable, V any](ca Cache[K, V], cacheFunc MapSingleFn[K, V], batchCacheFn MapBatchFn[K, V], inc IncreaseUpdate[K, V]) *MapCache[K, V] { func NewMapCache[K comparable, V any](ca Cache[K, V], cacheFunc MapSingleFn[K, V], batchCacheFn MapBatchFn[K, V], inc *IncreaseUpdate[K, V]) *MapCache[K, V] {
r := &MapCache[K, V]{ r := &MapCache[K, V]{
Cache: ca, Cache: ca,
mux: sync.Mutex{}, mux: sync.Mutex{},
@ -118,45 +118,50 @@ func (m *MapCache[K, V]) Flush(ctx context.Context) {
m.Cache.Flush(ctx) m.Cache.Flush(ctx)
} }
func (m *MapCache[K, V]) increaseUpdates(c context.Context, timeout time.Duration, data V, key K, params ...any) (V, error) {
var err error
nowTime := time.Now()
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
return data, err
}
fn := func() {
m.mux.Lock()
defer m.mux.Unlock()
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
return
}
dat, save, refresh, er := m.increaseUpdate.Fn(c, data, key, m.GetLastSetTime(c, key), params...)
if er != nil {
err = er
return
}
if refresh {
m.refresh.Refresh(c, key, params...)
}
if save {
m.Set(c, key, dat)
data = dat
}
}
if timeout > 0 {
er := helper.RunFnWithTimeout(c, timeout, fn)
if err == nil && er != nil {
return data, fmt.Errorf("increateUpdate cache %v err:[%s]", key, er)
}
} else {
fn()
}
return data, err
}
func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duration, params ...any) (V, error) { func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duration, params ...any) (V, error) {
data, ok := m.Get(c, key) data, ok := m.Get(c, key)
var err error var err error
if ok { if ok {
if m.increaseUpdate.Fn == nil || m.refresh == nil { if m.increaseUpdate == nil || m.refresh == nil {
return data, err return data, err
} }
nowTime := time.Now() return m.increaseUpdates(c, timeout, data, key, params...)
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
return data, err
}
fn := func() {
m.mux.Lock()
defer m.mux.Unlock()
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
return
}
dat, save, refresh, er := m.increaseUpdate.Fn(c, data, key, m.GetLastSetTime(c, key), params...)
if er != nil {
err = er
return
}
if refresh {
m.refresh.Refresh(c, key, params...)
}
if save {
m.Set(c, key, dat)
data = dat
}
}
if timeout > 0 {
er := helper.RunFnWithTimeout(c, timeout, fn, fmt.Sprintf("increateUpdate cache %v err", key))
if err == nil && er != nil {
return data, er
}
} else {
fn()
}
return data, err
} }
call := func() { call := func() {
m.mux.Lock() m.mux.Lock()

6
cache/vars.go vendored
View File

@ -12,7 +12,7 @@ type VarCache[T any] struct {
AnyCache[T] AnyCache[T]
setCacheFunc func(context.Context, ...any) (T, error) setCacheFunc func(context.Context, ...any) (T, error)
mutex sync.Mutex mutex sync.Mutex
increaseUpdate IncreaseUpdateVar[T] increaseUpdate *IncreaseUpdateVar[T]
refresh RefreshVar[T] refresh RefreshVar[T]
} }
@ -27,7 +27,7 @@ func (t *VarCache[T]) GetCache(ctx context.Context, timeout time.Duration, param
data, ok := t.Get(ctx) data, ok := t.Get(ctx)
var err error var err error
if ok { if ok {
if t.increaseUpdate.Fn != nil && t.refresh != nil { if t.increaseUpdate != nil && t.refresh != nil {
nowTime := time.Now() nowTime := time.Now()
if t.increaseUpdate.CycleTime() > nowTime.Sub(t.GetLastSetTime(ctx)) { if t.increaseUpdate.CycleTime() > nowTime.Sub(t.GetLastSetTime(ctx)) {
return data, nil return data, nil
@ -125,7 +125,7 @@ func (c *VarMemoryCache[T]) GetLastSetTime(_ context.Context) time.Time {
return c.v.Load().setTime return c.v.Load().setTime
} }
func NewVarCache[T any](cache AnyCache[T], fn func(context.Context, ...any) (T, error), inc IncreaseUpdateVar[T], ref RefreshVar[T]) *VarCache[T] { func NewVarCache[T any](cache AnyCache[T], fn func(context.Context, ...any) (T, error), inc *IncreaseUpdateVar[T], ref RefreshVar[T]) *VarCache[T] {
return &VarCache[T]{ return &VarCache[T]{
AnyCache: cache, setCacheFunc: fn, mutex: sync.Mutex{}, AnyCache: cache, setCacheFunc: fn, mutex: sync.Mutex{},
increaseUpdate: inc, increaseUpdate: inc,

View File

@ -97,8 +97,8 @@ func Divide[T constraints.Integer | constraints.Float](i, j T) T {
return i / j return i / j
} }
func CalTotalPage[T constraints.Integer](totalRows, size T) T { func DivideCeil[T constraints.Integer](num1, num2 T) T {
return T(math.Ceil(float64(totalRows) / float64(size))) return T(math.Ceil(float64(num1) / float64(num2)))
} }
type Counter[T constraints.Integer] func() T type Counter[T constraints.Integer] func() T

View File

@ -245,8 +245,8 @@ func TestCalTotalPage(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := CalTotalPage(tt.args.totalRows, tt.args.size); got != tt.want { if got := DivideCeil(tt.args.totalRows, tt.args.size); got != tt.want {
t.Errorf("CalTotalPage() = %v, want %v", got, tt.want) t.Errorf("DivideCeil() = %v, want %v", got, tt.want)
} }
}) })
} }

View File

@ -12,11 +12,12 @@ type QueryCondition struct {
Having SqlBuilder Having SqlBuilder
Limit int Limit int
Offset int Offset int
TotalRow int
In [][]any In [][]any
RelationFn []func() (bool, bool, *QueryCondition, RelationFn) RelationFn []func() (bool, bool, *QueryCondition, RelationFn)
} }
type RelationFn func() (func(any) []any, func(any, any), any, any, Relationship) type RelationFn func() (func(any) []any, func(any, any), func(bool) any, Relationship)
func Conditions(fns ...Condition) *QueryCondition { func Conditions(fns ...Condition) *QueryCondition {
r := &QueryCondition{} r := &QueryCondition{}
@ -78,6 +79,13 @@ func Limit(limit int) Condition {
} }
} }
// TotalRaw only effect on Pagination,when TotalRaw>0 ,will not query count
func TotalRaw(total int) Condition {
return func(c *QueryCondition) {
c.TotalRow = total
}
}
func Offset(offset int) Condition { func Offset(offset int) Condition {
return func(c *QueryCondition) { return func(c *QueryCondition) {
c.Offset = offset c.Offset = offset
@ -96,7 +104,7 @@ func WithCtx(ctx *context.Context) Condition {
} }
} }
func WithFn(getVal, isJoin bool, q *QueryCondition, fn func() (func(any) []any, func(any, any), any, any, Relationship)) Condition { func WithFn(getVal, isJoin bool, q *QueryCondition, fn func() (func(any) []any, func(any, any), func(bool) any, Relationship)) Condition {
return func(c *QueryCondition) { return func(c *QueryCondition) {
c.RelationFn = append(c.RelationFn, func() (bool, bool, *QueryCondition, RelationFn) { c.RelationFn = append(c.RelationFn, func() (bool, bool, *QueryCondition, RelationFn) {
return getVal, isJoin, q, fn return getVal, isJoin, q, fn

View File

@ -37,7 +37,7 @@ func pagination[T Model](db dbQuery, ctx context.Context, q *QueryCondition, pag
From: q.From, From: q.From,
Fields: "count(*) n", Fields: "count(*) n",
} }
if q.Group != "" { if q.Group != "" && q.TotalRow <= 0 {
qx.Fields = q.Fields qx.Fields = q.Fields
if qx.From == "" { if qx.From == "" {
qx.From = Table[T]() qx.From = Table[T]()
@ -55,11 +55,17 @@ func pagination[T Model](db dbQuery, ctx context.Context, q *QueryCondition, pag
Fields: "count(*) n", Fields: "count(*) n",
} }
} }
n, err := gets[count[T]](db, ctx, &qx) if q.TotalRow <= 0 {
total = n.N n, er := gets[count[T]](db, ctx, &qx)
if err != nil || total < 1 { total = n.N
return if er != nil || total < 1 {
err = er
return
}
} else {
total = q.TotalRow
} }
offset := 0 offset := 0
if page > 1 { if page > 1 {
offset = (page - 1) * q.Limit offset = (page - 1) * q.Limit

View File

@ -3,6 +3,7 @@ package model
import ( import (
"context" "context"
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
@ -24,7 +25,7 @@ const (
// Relationship join table // Relationship join table
// //
// RelationType HasOne| HasMany // # RelationType HasOne| HasMany
// //
// eg: hasOne, post has a user. ForeignKey is user's id , Local is post's userId field // eg: hasOne, post has a user. ForeignKey is user's id , Local is post's userId field
// //
@ -119,7 +120,7 @@ func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCon
for _, f := range q.RelationFn { for _, f := range q.RelationFn {
getVal, isJoin, qq, relationship := f() getVal, isJoin, qq, relationship := f()
idFn, assignmentFn, rr, rrs, ship := relationship() idFn, assignmentFn, varFn, ship := relationship()
if isJoin { if isJoin {
beforeFn = append(beforeFn, func() { beforeFn = append(beforeFn, func() {
parseBeforeJoin(qx, ship) parseBeforeJoin(qx, ship)
@ -167,15 +168,15 @@ func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCon
} }
qq.In = in qq.In = in
} }
err = ParseRelation(isPlural || ship.RelationType == HasMany, db, ctx, helper.Or(isPlural, rrs, rr), qq) err = ParseRelation(isPlural || ship.RelationType == HasMany, db, ctx, varFn(isPlural), qq)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if errors.Is(err, sql.ErrNoRows) {
err = nil err = nil
} else { } else {
return err return err
} }
} }
assignmentFn(r, helper.Or(isPlural, rrs, rr)) assignmentFn(r, varFn(isPlural))
return err return err
}) })
} }
@ -250,10 +251,15 @@ func SetHasMany[T, V any, K comparable](assignmentFn func(*T, *[]V), pIdFn func(
func RelationHasOne[M, P any, I constraints.Integer | constraints.Unsigned](fId func(*M) I, pId func(*P) I, setVal func(*M, *P), r Relationship) RelationFn { func RelationHasOne[M, P any, I constraints.Integer | constraints.Unsigned](fId func(*M) I, pId func(*P) I, setVal func(*M, *P), r Relationship) RelationFn {
idFn := GetWithID(fId) idFn := GetWithID(fId)
setFn := SetHasOne(setVal, fId, pId) setFn := SetHasOne(setVal, fId, pId)
return func() (func(any) []any, func(any, any), any, any, Relationship) { return func() (func(any) []any, func(any, any), func(bool) any, Relationship) {
var s P return idFn, setFn, func(isPlural bool) any {
var ss []P if isPlural {
return idFn, setFn, &s, &ss, r var ss []P
return &ss
}
var s P
return &s
}, r
} }
} }
@ -262,9 +268,11 @@ func RelationHasOne[M, P any, I constraints.Integer | constraints.Unsigned](fId
func RelationHasMany[M, P any, I constraints.Integer | constraints.Unsigned](mId func(*M) I, pId func(*P) I, setVal func(*M, *[]P), r Relationship) RelationFn { func RelationHasMany[M, P any, I constraints.Integer | constraints.Unsigned](mId func(*M) I, pId func(*P) I, setVal func(*M, *[]P), r Relationship) RelationFn {
idFn := GetWithID(mId) idFn := GetWithID(mId)
setFn := SetHasMany(setVal, mId, pId) setFn := SetHasMany(setVal, mId, pId)
return func() (func(any) []any, func(any, any), any, any, Relationship) { return func() (func(any) []any, func(any, any), func(bool) any, Relationship) {
var ss []P return idFn, setFn, func(_ bool) any {
return idFn, setFn, &ss, &ss, r var ss []P
return &ss
}, r
} }
} }

View File

@ -26,7 +26,7 @@ type ParsePagination struct {
} }
func NewParsePagination(totalRaw int, pageSize int, currentPage, step int, query string, path string) ParsePagination { func NewParsePagination(totalRaw int, pageSize int, currentPage, step int, query string, path string) ParsePagination {
return ParsePagination{TotalPage: number.CalTotalPage(totalRaw, pageSize), TotalRaw: totalRaw, PageSize: pageSize, CurrentPage: currentPage, Query: query, Path: path, Step: step} return ParsePagination{TotalPage: number.DivideCeil(totalRaw, pageSize), TotalRaw: totalRaw, PageSize: pageSize, CurrentPage: currentPage, Query: query, Path: path, Step: step}
} }
func Paginate(e Elements, p ParsePagination) string { func Paginate(e Elements, p ParsePagination) string {