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.TotalRows = totalRows
i.ginH["totalPage"] = number.CalTotalPage(totalRows, i.Param.PageSize)
i.ginH["totalPage"] = number.DivideCeil(totalRows, i.Param.PageSize)
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] {
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)
FlushPush(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] {
inc := helper.ParseArgs(cache.IncreaseUpdateVar[T]{}, a...)
inc := helper.ParseArgs((*cache.IncreaseUpdateVar[T])(nil), a...)
ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...)
v := cache.NewVarCache(c, fn, inc, ref)
FlushPush(v)

29
cache/map.go vendored
View File

@ -18,7 +18,7 @@ type MapCache[K comparable, V any] struct {
batchCacheFn MapBatchFn[K, V]
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)
increaseUpdate IncreaseUpdate[K, V]
increaseUpdate *IncreaseUpdate[K, V]
refresh Refresh[K, V]
}
type IncreaseUpdate[K comparable, V any] struct {
@ -26,16 +26,16 @@ type IncreaseUpdate[K comparable, V any] struct {
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)
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 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)
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]{
Cache: ca,
mux: sync.Mutex{},
@ -118,13 +118,8 @@ func (m *MapCache[K, V]) Flush(ctx context.Context) {
m.Cache.Flush(ctx)
}
func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duration, params ...any) (V, error) {
data, ok := m.Get(c, key)
func (m *MapCache[K, V]) increaseUpdates(c context.Context, timeout time.Duration, data V, key K, params ...any) (V, error) {
var err error
if ok {
if m.increaseUpdate.Fn == nil || m.refresh == nil {
return data, err
}
nowTime := time.Now()
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
return data, err
@ -149,15 +144,25 @@ func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duratio
}
}
if timeout > 0 {
er := helper.RunFnWithTimeout(c, timeout, fn, fmt.Sprintf("increateUpdate cache %v err", key))
er := helper.RunFnWithTimeout(c, timeout, fn)
if err == nil && er != nil {
return data, er
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) {
data, ok := m.Get(c, key)
var err error
if ok {
if m.increaseUpdate == nil || m.refresh == nil {
return data, err
}
return m.increaseUpdates(c, timeout, data, key, params...)
}
call := func() {
m.mux.Lock()
defer m.mux.Unlock()

6
cache/vars.go vendored
View File

@ -12,7 +12,7 @@ type VarCache[T any] struct {
AnyCache[T]
setCacheFunc func(context.Context, ...any) (T, error)
mutex sync.Mutex
increaseUpdate IncreaseUpdateVar[T]
increaseUpdate *IncreaseUpdateVar[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)
var err error
if ok {
if t.increaseUpdate.Fn != nil && t.refresh != nil {
if t.increaseUpdate != nil && t.refresh != nil {
nowTime := time.Now()
if t.increaseUpdate.CycleTime() > nowTime.Sub(t.GetLastSetTime(ctx)) {
return data, nil
@ -125,7 +125,7 @@ func (c *VarMemoryCache[T]) GetLastSetTime(_ context.Context) time.Time {
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]{
AnyCache: cache, setCacheFunc: fn, mutex: sync.Mutex{},
increaseUpdate: inc,

View File

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

View File

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

View File

@ -12,11 +12,12 @@ type QueryCondition struct {
Having SqlBuilder
Limit int
Offset int
TotalRow int
In [][]any
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 {
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 {
return func(c *QueryCondition) {
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) {
c.RelationFn = append(c.RelationFn, func() (bool, bool, *QueryCondition, RelationFn) {
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,
Fields: "count(*) n",
}
if q.Group != "" {
if q.Group != "" && q.TotalRow <= 0 {
qx.Fields = q.Fields
if qx.From == "" {
qx.From = Table[T]()
@ -55,11 +55,17 @@ func pagination[T Model](db dbQuery, ctx context.Context, q *QueryCondition, pag
Fields: "count(*) n",
}
}
n, err := gets[count[T]](db, ctx, &qx)
if q.TotalRow <= 0 {
n, er := gets[count[T]](db, ctx, &qx)
total = n.N
if err != nil || total < 1 {
if er != nil || total < 1 {
err = er
return
}
} else {
total = q.TotalRow
}
offset := 0
if page > 1 {
offset = (page - 1) * q.Limit

View File

@ -3,6 +3,7 @@ package model
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice"
@ -24,7 +25,7 @@ const (
// 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
//
@ -119,7 +120,7 @@ func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCon
for _, f := range q.RelationFn {
getVal, isJoin, qq, relationship := f()
idFn, assignmentFn, rr, rrs, ship := relationship()
idFn, assignmentFn, varFn, ship := relationship()
if isJoin {
beforeFn = append(beforeFn, func() {
parseBeforeJoin(qx, ship)
@ -167,15 +168,15 @@ func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCon
}
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 == sql.ErrNoRows {
if errors.Is(err, sql.ErrNoRows) {
err = nil
} else {
return err
}
}
assignmentFn(r, helper.Or(isPlural, rrs, rr))
assignmentFn(r, varFn(isPlural))
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 {
idFn := GetWithID(fId)
setFn := SetHasOne(setVal, fId, pId)
return func() (func(any) []any, func(any, any), any, any, Relationship) {
var s P
return func() (func(any) []any, func(any, any), func(bool) any, Relationship) {
return idFn, setFn, func(isPlural bool) any {
if isPlural {
var ss []P
return idFn, setFn, &s, &ss, r
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 {
idFn := GetWithID(mId)
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) {
return idFn, setFn, func(_ bool) any {
var ss []P
return idFn, setFn, &ss, &ss, r
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 {
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 {