wp-go/cache/reload/reload.go

321 lines
6.0 KiB
Go
Raw Normal View History

package reload
2023-03-04 06:44:51 +00:00
import (
2023-11-12 13:39:04 +00:00
"github.com/fthvgb1/wp-go/helper"
2023-04-25 12:58:22 +00:00
"github.com/fthvgb1/wp-go/helper/number"
2023-10-14 06:57:57 +00:00
"github.com/fthvgb1/wp-go/helper/slice"
2023-03-04 06:44:51 +00:00
"github.com/fthvgb1/wp-go/safety"
"sync"
2023-03-04 06:44:51 +00:00
)
2023-10-14 06:57:57 +00:00
type queue struct {
fn func()
order float64
name string
2023-10-14 06:57:57 +00:00
}
var calls = safety.NewSlice(make([]queue, 0))
var callsM = safety.NewMap[string, func()]()
2023-03-06 15:43:58 +00:00
var anyMap = safety.NewMap[string, any]()
type safetyVar[T, A any] struct {
Val *safety.Var[val[T]]
mutex sync.Mutex
}
type val[T any] struct {
2023-04-25 12:58:22 +00:00
v T
ok bool
counter number.Counter[int]
}
type safetyMap[K comparable, V, A any] struct {
val *safety.Map[K, V]
mutex sync.Mutex
}
var safetyMaps = safety.NewMap[string, any]()
var safetyMapLock = sync.Mutex{}
var flushMapFn = safety.NewMap[string, func(any)]()
func FlushMapVal[T any](namespace string, key ...T) {
fn, ok := flushMapFn.Load(namespace)
if !ok || len(key) < 1 {
return
}
fn(key)
}
2023-10-24 08:06:59 +00:00
func FlushAnyVal(namespaces ...string) {
for _, namespace := range namespaces {
fn, ok := callsM.Load(namespace)
if !ok {
2023-10-24 08:07:48 +00:00
continue
2023-10-24 08:06:59 +00:00
}
fn()
}
}
2023-04-25 12:58:22 +00:00
func GetAnyMapFnBys[K comparable, V, A any](namespace string, fn func(A) V) func(key K, args A) V {
m := safetyMapFn[K, V, A](namespace)
return func(key K, a A) V {
v, ok := m.val.Load(key)
if ok {
return v
}
m.mutex.Lock()
2023-11-12 13:39:04 +00:00
defer m.mutex.Unlock()
v, ok = m.val.Load(key)
if ok {
return v
}
v = fn(a)
m.val.Store(key, v)
return v
2023-03-06 15:43:58 +00:00
}
2023-02-18 16:14:33 +00:00
}
func safetyMapFn[K comparable, V, A any](namespace string, args ...any) *safetyMap[K, V, A] {
vv, ok := safetyMaps.Load(namespace)
var m *safetyMap[K, V, A]
2023-03-18 05:17:21 +00:00
if ok {
m = vv.(*safetyMap[K, V, A])
} else {
safetyMapLock.Lock()
2023-11-12 13:39:04 +00:00
defer safetyMapLock.Unlock()
vv, ok = safetyMaps.Load(namespace)
if ok {
m = vv.(*safetyMap[K, V, A])
} else {
m = &safetyMap[K, V, A]{safety.NewMap[K, V](), sync.Mutex{}}
ord, _ := parseArgs(args...)
flushMapFn.Store(namespace, func(a any) {
k, ok := a.([]K)
if !ok && len(k) > 0 {
return
}
for _, key := range k {
m.val.Delete(key)
}
})
Push(func() {
m.val.Flush()
}, ord, namespace)
safetyMaps.Store(namespace, m)
}
2023-03-18 05:17:21 +00:00
}
return m
2023-03-18 05:17:21 +00:00
}
2023-02-18 16:14:33 +00:00
2023-11-12 13:39:04 +00:00
func GetAnyValMapBy[K comparable, V, A any](namespace string, key K, a A, fn func(A) (V, bool), args ...any) V {
m := safetyMapFn[K, V, A](namespace, args...)
v, ok := m.val.Load(key)
2023-03-04 06:44:51 +00:00
if ok {
return v
}
m.mutex.Lock()
2023-11-12 13:39:04 +00:00
defer m.mutex.Unlock()
v, ok = m.val.Load(key)
if ok {
return v
}
2023-11-12 13:39:04 +00:00
v, ok = fn(a)
if ok {
m.val.Store(key, v)
}
2023-03-04 06:44:51 +00:00
return v
}
func anyVal[T, A any](namespace string, counter bool, args ...any) *safetyVar[T, A] {
var vv *safetyVar[T, A]
vvv, ok := safetyMaps.Load(namespace)
if ok {
vv = vvv.(*safetyVar[T, A])
} else {
safetyMapLock.Lock()
2023-11-12 13:39:04 +00:00
defer safetyMapLock.Unlock()
vvv, ok = safetyMaps.Load(namespace)
if ok {
vv = vvv.(*safetyVar[T, A])
} else {
2023-04-25 12:58:22 +00:00
v := val[T]{}
if counter {
v.counter = number.Counters[int]()
}
vv = &safetyVar[T, A]{safety.NewVar(v), sync.Mutex{}}
ord, _ := parseArgs(args...)
Push(func() {
vv.Val.Flush()
}, ord, namespace)
safetyMaps.Store(namespace, vv)
}
}
2023-04-25 12:58:22 +00:00
return vv
}
2023-11-12 13:39:04 +00:00
func GetAnyValBy[T, A any](namespace string, a A, fn func(A) (T, bool), args ...any) T {
var vv = anyVal[T, A](namespace, true, args...)
2023-04-25 12:58:22 +00:00
var ok bool
v := vv.Val.Load()
if v.ok {
return v.v
}
vv.mutex.Lock()
2023-11-12 13:39:04 +00:00
defer vv.mutex.Unlock()
2023-04-25 12:58:22 +00:00
v = vv.Val.Load()
if v.ok {
return v.v
}
v.v, ok = fn(a)
2023-11-12 13:39:04 +00:00
if v.counter == nil {
v.counter = number.Counters[int]()
}
2023-04-25 12:58:22 +00:00
times := v.counter()
2023-11-12 13:39:04 +00:00
tryTimes := helper.ParseArgs(1, args...)
2023-04-25 13:05:10 +00:00
if ok || times >= tryTimes {
2023-04-25 12:58:22 +00:00
v.ok = true
vv.Val.Store(v)
}
return v.v
}
2023-11-12 13:39:04 +00:00
func GetAnyValBys[T, A any](namespace string, a A, fn func(A) (T, bool), args ...any) T {
var vv = anyVal[T, A](namespace, false, args...)
v := vv.Val.Load()
if v.ok {
return v.v
}
vv.mutex.Lock()
2023-11-12 13:39:04 +00:00
defer vv.mutex.Unlock()
v = vv.Val.Load()
if v.ok {
return v.v
}
2023-11-12 13:39:04 +00:00
v.v, v.ok = fn(a)
vv.Val.Store(v)
return v.v
}
func Vars[T any](defaults T, args ...any) *safety.Var[T] {
ss := safety.NewVar(defaults)
ord, name := parseArgs(args...)
Push(func() {
ss.Store(defaults)
}, ord, name)
return ss
}
2023-10-14 06:57:57 +00:00
func parseArgs(a ...any) (ord float64, name string) {
if len(a) > 0 {
for _, arg := range a {
v, ok := arg.(float64)
if ok {
ord = v
}
vv, ok := arg.(string)
if ok {
name = vv
}
}
2023-10-14 06:57:57 +00:00
}
return ord, name
2023-10-14 06:57:57 +00:00
}
func VarsBy[T any](fn func() T, args ...any) *safety.Var[T] {
ss := safety.NewVar(fn())
ord, name := parseArgs(args...)
Push(func() {
ss.Store(fn())
}, ord, name)
return ss
}
func MapBy[K comparable, T any](fn func(*safety.Map[K, T]), args ...any) *safety.Map[K, T] {
2023-08-26 14:01:20 +00:00
m := safety.NewMap[K, T]()
if fn != nil {
fn(m)
}
ord, name := parseArgs(args...)
Push(func() {
m.Flush()
if fn != nil {
fn(m)
}
}, ord, name)
2023-08-26 14:01:20 +00:00
return m
}
func SafeMap[K comparable, T any](args ...any) *safety.Map[K, T] {
2023-08-26 14:01:20 +00:00
m := safety.NewMap[K, T]()
ord, name := parseArgs(args...)
Push(func() {
2023-08-26 14:01:20 +00:00
m.Flush()
}, ord, name)
2023-08-26 14:01:20 +00:00
return m
}
func Push(fn func(), a ...any) {
ord, name := parseArgs(a...)
calls.Append(queue{fn, ord, name})
if name != "" {
callsM.Store(name, fn)
}
}
func Reload() {
2023-10-23 14:38:52 +00:00
callsM.Flush()
flushMapFn.Flush()
2023-10-30 14:21:08 +00:00
callll := calls.Load()
slice.SimpleSort(callll, slice.DESC, func(t queue) float64 {
return t.order
2023-10-14 06:57:57 +00:00
})
2023-10-30 14:21:08 +00:00
for _, call := range callll {
2023-10-14 06:57:57 +00:00
call.fn()
}
2023-10-23 14:38:52 +00:00
return
}
2023-11-28 14:46:22 +00:00
type Any[T any] struct {
fn func() T
v *safety.Var[T]
isUseManger *safety.Var[bool]
}
func FnVal[T any](name string, t T, fn func() T) func() T {
if fn == nil {
fn = func() T {
return t
}
} else {
t = fn()
}
p := safety.NewVar(t)
e := Any[T]{
fn: fn,
v: p,
isUseManger: safety.NewVar(false),
}
Push(func() {
if !e.isUseManger.Load() {
e.v.Store(fn())
}
})
anyMap.Store(name, e)
return func() T {
return e.v.Load()
}
}
func ChangeFnVal[T any](name string, val T, coverConf bool) {
2023-11-28 14:46:22 +00:00
v, ok := anyMap.Load(name)
if !ok {
return
}
vv, ok := v.(Any[T])
if !ok {
return
}
if coverConf && !vv.isUseManger.Load() {
2023-11-28 14:46:22 +00:00
vv.isUseManger.Store(true)
}
vv.v.Store(val)
}