修复bug reload升级 handlecall 拉伸

This commit is contained in:
xing 2023-04-04 23:02:54 +08:00
parent 1ecb338af5
commit 78f0c0a87a
11 changed files with 263 additions and 84 deletions

View File

@ -1,9 +1,8 @@
package reload
import (
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/safety"
"strings"
"sync"
)
var calls []func()
@ -12,37 +11,118 @@ var str = safety.NewMap[string, string]()
var anyMap = safety.NewMap[string, any]()
func GetAnyValBy[T any](k string, fn func() T) T {
v, ok := anyMap.Load(k)
if ok {
return v.(T)
}
vv := fn()
anyMap.Store(k, vv)
return vv
type safetyVar[T, A any] struct {
Val *safety.Var[val[T]]
mutex sync.Mutex
}
func GetAnyValBys[T, A any](k string, a A, fn func(A) T) T {
v, ok := anyMap.Load(k)
if ok {
return v.(T)
}
vv := fn(a)
anyMap.Store(k, vv)
return vv
type val[T any] struct {
v T
ok bool
}
type safetyMap[K comparable, V, A any] struct {
val *safety.Map[K, V]
mutex sync.Mutex
}
func GetStrBy[T any](key, delimiter string, t T, fn ...func(T) string) string {
v, ok := str.Load(key)
var safetyMaps = safety.NewMap[string, any]()
var safetyMapLock = sync.Mutex{}
func SafetyMapByFn[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()
v, ok = m.val.Load(key)
if ok {
m.mutex.Unlock()
return v
}
v = fn(a)
m.val.Store(key, v)
m.mutex.Unlock()
return v
}
}
func safetyMapFn[K comparable, V, A any](namespace string) *safetyMap[K, V, A] {
vv, ok := safetyMaps.Load(namespace)
var m *safetyMap[K, V, A]
if ok {
m = vv.(*safetyMap[K, V, A])
} else {
safetyMapLock.Lock()
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{}}
Push(func() {
m.val.Flush()
})
safetyMaps.Store(namespace, m)
}
safetyMapLock.Unlock()
}
return m
}
func SafetyMapBy[K comparable, V, A any](namespace string, key K, a A, fn func(A) V) V {
m := safetyMapFn[K, V, A](namespace)
v, ok := m.val.Load(key)
if ok {
return v
}
v = strings.Join(slice.Map(fn, func(vv func(T) string) string {
return vv(t)
}), delimiter)
str.Store(key, v)
m.mutex.Lock()
v, ok = m.val.Load(key)
if ok {
m.mutex.Unlock()
return v
}
v = fn(a)
m.val.Store(key, v)
m.mutex.Unlock()
return v
}
func GetAnyValBys[T, A any](namespace string, a A, fn func(A) T) T {
var vv *safetyVar[T, A]
vvv, ok := safetyMaps.Load(namespace)
if ok {
vv = vvv.(*safetyVar[T, A])
} else {
safetyMapLock.Lock()
vvv, ok = safetyMaps.Load(namespace)
if ok {
vv = vvv.(*safetyVar[T, A])
} else {
vv = &safetyVar[T, A]{safety.NewVar(val[T]{}), sync.Mutex{}}
Push(func() {
vv.Val.Flush()
})
safetyMaps.Store(namespace, vv)
}
safetyMapLock.Unlock()
}
v := vv.Val.Load()
if v.ok {
return v.v
}
vv.mutex.Lock()
v = vv.Val.Load()
if v.ok {
vv.mutex.Unlock()
return v.v
}
v.v = fn(a)
v.ok = true
vv.Val.Store(v)
vv.mutex.Unlock()
return v.v
}
func Vars[T any](defaults T) *safety.Var[T] {
ss := safety.NewVar(defaults)
calls = append(calls, func() {
@ -68,4 +148,5 @@ func Reload() {
}
anyMap.Flush()
str.Flush()
safetyMaps.Flush()
}

View File

@ -34,23 +34,38 @@ func Init(fs embed.FS) {
logs.ErrPrintln(err, "解析colorscheme失败")
}
var pipe = wp.HandlePipe(wp.Render, widget.MiddleWare(ready)...)
var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, data)...)
func Hook(h *wp.Handle) {
pipe(h)
}
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
wp.InitThemeArgAndConfig(configs, h)
h.GetPassword()
next(h)
}
func data(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
if h.Scene() == constraints.Detail {
wp.Details(h)
} else {
wp.Indexs(h)
}
h.DetermineHandleFns()
next(h)
}
func configs(h *wp.Handle) *wp.Handle {
h.PushComponentFilterFn(widgets.Search, func(h *wp.Handle, s string, args ...any) string {
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
})
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushCacheGroupHeadScript("CalCustomBackGround", 10, CalCustomBackGround, colorSchemeCss)
h.CommonComponents()
h.PushHandleFn(constraints.Ok, wp.NewHandleFn(components.WidgetArea, 20))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(customHeader, 10))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(wp.Indexs, 100))
h.PushHandleFn(constraints.Detail, wp.NewHandleFn(wp.Details, 100))
next(h)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50))
h.PushHandleFn(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50))
return h
}

View File

@ -7,7 +7,7 @@ import (
)
func pushScripts(h *wp.Handle) {
h.PushCacheGroupFooterScript("head", 30, func(h *wp.Handle) string {
h.PushCacheGroupHeadScript("head", 30, func(h *wp.Handle) string {
head := headScript
if "dark" == wpconfig.GetThemeModsVal(ThemeName, "colorscheme", "light") {
head = fmt.Sprintf("%s\n%s", headScript, ` <link rel="stylesheet" id="twentyseventeen-colors-dark-css" href="/wp-content/themes/twentyseventeen/assets/css/colors-dark.css?ver=20191025" media="all">`)

View File

@ -43,29 +43,35 @@ var paginate = func() plugins.PageEle {
return p
}()
var pipe = wp.HandlePipe(wp.Render, widget.MiddleWare(ready)...)
var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, data)...)
func Hook(h *wp.Handle) {
pipe(h)
}
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
h.GetPassword()
func configs(h *wp.Handle) *wp.Handle {
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(calClass, 20))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(index, 100))
h.PushHandleFn(constraints.Detail, wp.NewHandleFn(detail, 100))
h.PushGroupHandleFn(constraints.AllStats, 90, wp.PreCodeAndStats, wp.PreTemplate, errorsHandle)
h.PushCacheGroupHeadScript("colorScheme-customHeader", 10, colorScheme, customHeader)
h.PushHandleFn(constraints.Ok, wp.NewHandleFn(components.WidgetArea, 20))
components.WidgetArea(h)
pushScripts(h)
h.SetData("HeaderImage", getHeaderImage(h))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(func(h *wp.Handle) {
h.SetData("HeaderImage", getHeaderImage(h))
}, 10))
h.SetComponentsArgs(widgets.Widget, map[string]string{
"{$before_widget}": `<section id="%s" class="%s">`,
"{$after_widget}": `</section>`,
})
h.PushGroupHandleFn(constraints.AllStats, 90, wp.PreTemplate, errorsHandle)
h.CommonComponents()
wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 10))
h.PushHandleFn(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10))
return h
}
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
wp.InitThemeArgAndConfig(configs, h)
h.GetPassword()
next(h)
}
@ -94,6 +100,17 @@ func errorsHandle(h *wp.Handle) {
}
}
func data(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
if h.Scene() == constraints.Detail {
detail(h)
} else {
index(h)
}
wp.PreCodeAndStats(h)
h.DetermineHandleFns()
next(h)
}
func index(h *wp.Handle) {
if h.Scene() == constraints.Detail {
return

View File

@ -68,7 +68,7 @@ func RecentComments(h *wp.Handle, id string) string {
<span class="comment-author-link">%s</span>发表在
<a href="/p/%v#comment-%v">%s</a>
</li>`, t.CommentAuthor, t.CommentId, t.CommentPostId, t.PostTitle)
</li>`, t.CommentAuthor, t.CommentPostId, t.CommentId, t.PostTitle)
})
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
return h.ComponentFilterFnHook(widgets.RecentComments, str.Replace(s, args))

View File

@ -18,7 +18,7 @@ func (h *Handle) DisplayHeaderText() bool {
func (h *Handle) GetCustomHeader() (r models.PostThumbnail, isRand bool) {
var err error
hss := reload.GetAnyValBys("headerImages", h.theme, func(theme string) []models.PostThumbnail {
img := reload.GetAnyValBys("headerImages", h.theme, func(theme string) []models.PostThumbnail {
hs, er := h.GetHeaderImages(h.theme)
if er != nil {
err = er
@ -30,7 +30,7 @@ func (h *Handle) GetCustomHeader() (r models.PostThumbnail, isRand bool) {
logs.ErrPrintln(err, "获取页眉背景图失败")
return
}
hs := slice.Copy(hss)
hs := slice.Copy(img)
if len(hs) < 1 {
return

View File

@ -6,11 +6,8 @@ import (
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"sync"
)
var logoLock = sync.Mutex{}
func CalCustomLogo(h *Handle) (r string) {
id := uint64(h.themeMods.CustomLogo)
if id < 1 {
@ -33,9 +30,7 @@ func CalCustomLogo(h *Handle) (r string) {
"decoding": "async",
//"loading":"lazy",
}
logoLock.Lock()
img := wpconfig.Thumbnail(logo.AttachmentMetadata, siz, "", "")
logoLock.Unlock()
imgx["srcset"] = img.Srcset
imgx["sizes"] = img.Sizes
imgx["src"] = img.Path

View File

@ -101,19 +101,33 @@ func (d *DetailHandle) ContextPost() {
}
func (d *DetailHandle) Render() {
d.PushHandleFn(constraints.Ok, NewHandleFn(func(h *Handle) {
d.PasswordProject()
d.RenderComment()
d.ginH["post"] = d.Post
reply := ""
if d.Post.CommentStatus == "open" && wpconfig.GetOption("thread_comments") == "1" {
reply = `<script src='/wp-includes/js/comment-reply.min.js' id='comment-reply-js'></script>`
}
d.PushGroupFooterScript(10, reply)
}, 10))
d.Handle.Render()
}
func DetailRender(h *Handle) {
if h.Stats != constraints.Ok {
return
}
d := h.Detail
d.PasswordProject()
d.RenderComment()
d.ginH["post"] = d.Post
reply := ""
if d.Post.CommentStatus == "open" && wpconfig.GetOption("thread_comments") == "1" {
reply = `<script src='/wp-includes/js/comment-reply.min.js' id='comment-reply-js'></script>`
}
d.PushGroupFooterScript(10, reply)
d.PushHandleFn(constraints.Ok, NewHandleFn(func(h *Handle) {
d.PasswordProject()
d.RenderComment()
d.ginH["post"] = d.Post
}, 10))
d.Handle.Render()
}
func Details(h *Handle) {

View File

@ -156,6 +156,16 @@ func (i *IndexHandle) Render() {
i.Handle.Render()
}
func IndexRender(h *Handle) {
if h.scene == constraints.Detail || h.Stats != constraints.Ok {
return
}
i := h.Index
i.ExecPostsPlugin()
i.Pagination()
i.ginH["posts"] = i.Posts
}
func Indexs(h *Handle) {
if h.Scene() == constraints.Detail {
return
@ -171,7 +181,9 @@ func (i *IndexHandle) MarkSticky(posts *[]models.Posts) {
if len(a) < 1 {
return
}
m := i.StickMapPosts()
*posts = append(a, slice.Filter(*posts, func(post models.Posts, _ int) bool {
return !i.IsStick(post.Id)
_, ok := m[post.Id]
return !ok
})...)
}

View File

@ -14,7 +14,7 @@ import (
)
func (h *Handle) StickPosts() []models.Posts {
return reload.GetAnyValBys("stickPosts", h, func(h *Handle) (r []models.Posts) {
return reload.GetAnyValBys("stickPostsSlice", h, func(h *Handle) (r []models.Posts) {
v := wpconfig.GetOption("sticky_posts")
if v == "" {
return

View File

@ -1,6 +1,7 @@
package wp
import (
"fmt"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
@ -12,7 +13,6 @@ import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
"sync"
)
type Handle struct {
@ -35,10 +35,16 @@ type Handle struct {
abort bool
componentsArgs map[string]any
componentFilterFn map[string][]func(*Handle, string, ...any) string
handleCall []HandleCall
}
var configHandle = reload.Vars(&Handle{})
var configHandleMux = sync.Mutex{}
func (h *Handle) HandleCall() []HandleCall {
return h.handleCall
}
func (h *Handle) SetHandleCall(handleCall []HandleCall) {
h.handleCall = handleCall
}
type HandlePlugins map[string]HandleFn[*Handle]
@ -60,17 +66,21 @@ type HandleCall struct {
}
func InitThemeArgAndConfig(fn func(*Handle) *Handle, h *Handle) {
hh := configHandle.Load()
if len(hh.handleFns) < 1 {
configHandleMux.Lock()
hh = configHandle.Load()
if len(hh.handleFns) < 1 {
hh = fn(h)
configHandle.Store(hh)
}
configHandleMux.Unlock()
hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle {
h.components = make(map[string][]Components[string])
h.handleFns = make(map[int][]HandleCall)
h.componentsArgs = make(map[string]any)
h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string)
hh := fn(h)
return *hh
})
m := make(map[string][]Components[string])
for k, v := range hh.components {
vv := make([]Components[string], len(v))
copy(vv, v)
m[k] = vv // slice.Copy(v)
}
h.components = hh.components
h.components = m // maps.Copy(hh.components)
h.handleFns = hh.handleFns
h.componentsArgs = hh.componentsArgs
h.componentFilterFn = hh.componentFilterFn
@ -193,17 +203,13 @@ func NewHandle(c *gin.Context, scene int, theme string) *Handle {
mods, err := wpconfig.GetThemeMods(theme)
logs.ErrPrintln(err, "获取mods失败")
return &Handle{
C: c,
theme: theme,
Session: sessions.Default(c),
ginH: gin.H{},
scene: scene,
Stats: constraints.Ok,
themeMods: mods,
components: make(map[string][]Components[string]),
handleFns: make(map[int][]HandleCall),
componentsArgs: make(map[string]any),
componentFilterFn: make(map[string][]func(*Handle, string, ...any) string),
C: c,
theme: theme,
Session: sessions.Default(c),
ginH: gin.H{},
scene: scene,
Stats: constraints.Ok,
themeMods: mods,
}
}
@ -249,8 +255,11 @@ func (h *Handle) PushCacheGroupFooterScript(key string, order int, fns ...func(*
h.PushGroupCacheComponentFn(constraints.FooterScript, key, order, fns...)
}
func (h *Handle) PushGroupCacheComponentFn(name, key string, order int, fns ...func(*Handle) string) {
v := reload.GetStrBy(key, "\n", h, fns...)
h.PushGroupComponentStrs(name, order, v)
h.PushComponents(name, h.NewCacheComponent(key, order, func(h *Handle) string {
return strings.Join(slice.Map(fns, func(t func(*Handle) string) string {
return t(h)
}), "\n")
}))
}
func (h *Handle) GetPassword() {
@ -360,7 +369,7 @@ func CalComponents(h *Handle) {
if component.Fn != nil {
v := ""
if component.CacheKey != "" {
v = reload.GetAnyValBys(component.CacheKey, h, component.Fn)
v = reload.SafetyMapBy("calComponent", component.CacheKey, h, component.Fn)
} else {
v = component.Fn(h)
}
@ -386,6 +395,42 @@ func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
}, initial)
}
func DetermineHandleFn(h *Handle) []HandleCall {
calls, ok := h.handleFns[h.Stats]
var fns []HandleCall
if ok {
fns = append(fns, calls...)
}
calls, ok = h.handleFns[h.scene]
if ok {
fns = append(fns, calls...)
}
calls, ok = h.handleFns[constraints.AllStats]
if ok {
fns = append(fns, calls...)
}
slice.Sort(fns, func(i, j HandleCall) bool {
return i.Order > j.Order
})
return fns
}
func (h *Handle) DetermineHandleFns() {
key := fmt.Sprintf("%d-%d", h.scene, h.Stats)
h.handleCall = reload.SafetyMapBy("handleCalls", key, h, func(h *Handle) []HandleCall {
return DetermineHandleFn(h)
})
}
func ExecuteHandleFn(h *Handle) {
for _, fn := range h.handleCall {
fn.Fn(h)
if h.abort {
break
}
}
}
func Render(h *Handle) {
switch h.scene {
case constraints.Detail: