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

View File

@ -34,23 +34,38 @@ func Init(fs embed.FS) {
logs.ErrPrintln(err, "解析colorscheme失败") 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) { func Hook(h *wp.Handle) {
pipe(h) pipe(h)
} }
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
wp.InitThemeArgAndConfig(configs, h)
h.GetPassword() 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 { 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"`) return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
}) })
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...) wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushCacheGroupHeadScript("CalCustomBackGround", 10, CalCustomBackGround, colorSchemeCss) h.PushCacheGroupHeadScript("CalCustomBackGround", 10, CalCustomBackGround, colorSchemeCss)
h.CommonComponents()
h.PushHandleFn(constraints.Ok, wp.NewHandleFn(components.WidgetArea, 20)) h.PushHandleFn(constraints.Ok, wp.NewHandleFn(components.WidgetArea, 20))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(customHeader, 10)) h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(customHeader, 10))
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(wp.Indexs, 100)) h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50))
h.PushHandleFn(constraints.Detail, wp.NewHandleFn(wp.Details, 100)) h.PushHandleFn(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50))
next(h) return h
} }

View File

@ -7,7 +7,7 @@ import (
) )
func pushScripts(h *wp.Handle) { 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 head := headScript
if "dark" == wpconfig.GetThemeModsVal(ThemeName, "colorscheme", "light") { 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">`) 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 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) { func Hook(h *wp.Handle) {
pipe(h) pipe(h)
} }
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func configs(h *wp.Handle) *wp.Handle {
h.GetPassword()
wphandle.RegisterPlugins(h, config.GetConfig().Plugins...) wphandle.RegisterPlugins(h, config.GetConfig().Plugins...)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(calClass, 20)) 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.PushCacheGroupHeadScript("colorScheme-customHeader", 10, colorScheme, customHeader)
h.PushHandleFn(constraints.Ok, wp.NewHandleFn(components.WidgetArea, 20)) components.WidgetArea(h)
pushScripts(h) pushScripts(h)
h.PushHandleFn(constraints.AllStats, wp.NewHandleFn(func(h *wp.Handle) {
h.SetData("HeaderImage", getHeaderImage(h)) h.SetData("HeaderImage", getHeaderImage(h))
}, 10))
h.SetComponentsArgs(widgets.Widget, map[string]string{ h.SetComponentsArgs(widgets.Widget, map[string]string{
"{$before_widget}": `<section id="%s" class="%s">`, "{$before_widget}": `<section id="%s" class="%s">`,
"{$after_widget}": `</section>`, "{$after_widget}": `</section>`,
}) })
h.PushGroupHandleFn(constraints.AllStats, 90, wp.PreTemplate, errorsHandle)
h.CommonComponents()
wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm) 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) 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) { func index(h *wp.Handle) {
if h.Scene() == constraints.Detail { if h.Scene() == constraints.Detail {
return return

View File

@ -68,7 +68,7 @@ func RecentComments(h *wp.Handle, id string) string {
<span class="comment-author-link">%s</span>发表在 <span class="comment-author-link">%s</span>发表在
<a href="/p/%v#comment-%v">%s</a> <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")) s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
return h.ComponentFilterFnHook(widgets.RecentComments, str.Replace(s, args)) 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) { func (h *Handle) GetCustomHeader() (r models.PostThumbnail, isRand bool) {
var err error 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) hs, er := h.GetHeaderImages(h.theme)
if er != nil { if er != nil {
err = er err = er
@ -30,7 +30,7 @@ func (h *Handle) GetCustomHeader() (r models.PostThumbnail, isRand bool) {
logs.ErrPrintln(err, "获取页眉背景图失败") logs.ErrPrintln(err, "获取页眉背景图失败")
return return
} }
hs := slice.Copy(hss) hs := slice.Copy(img)
if len(hs) < 1 { if len(hs) < 1 {
return return

View File

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

View File

@ -101,21 +101,35 @@ func (d *DetailHandle) ContextPost() {
} }
func (d *DetailHandle) Render() { func (d *DetailHandle) Render() {
d.PushHandleFn(constraints.Ok, NewHandleFn(func(h *Handle) {
d.PasswordProject()
d.RenderComment()
d.ginH["post"] = d.Post
reply := "" reply := ""
if d.Post.CommentStatus == "open" && wpconfig.GetOption("thread_comments") == "1" { 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>` reply = `<script src='/wp-includes/js/comment-reply.min.js' id='comment-reply-js'></script>`
} }
d.PushGroupFooterScript(10, reply) d.PushGroupFooterScript(10, reply)
d.PushHandleFn(constraints.Ok, NewHandleFn(func(h *Handle) {
d.PasswordProject()
d.RenderComment()
d.ginH["post"] = d.Post
}, 10)) }, 10))
d.Handle.Render() 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)
}
func Details(h *Handle) { func Details(h *Handle) {
_ = h.Detail.BuildDetailData() _ = h.Detail.BuildDetailData()
PreCodeAndStats(h) PreCodeAndStats(h)

View File

@ -156,6 +156,16 @@ func (i *IndexHandle) Render() {
i.Handle.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) { func Indexs(h *Handle) {
if h.Scene() == constraints.Detail { if h.Scene() == constraints.Detail {
return return
@ -171,7 +181,9 @@ func (i *IndexHandle) MarkSticky(posts *[]models.Posts) {
if len(a) < 1 { if len(a) < 1 {
return return
} }
m := i.StickMapPosts()
*posts = append(a, slice.Filter(*posts, func(post models.Posts, _ int) bool { *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 { 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") v := wpconfig.GetOption("sticky_posts")
if v == "" { if v == "" {
return return

View File

@ -1,6 +1,7 @@
package wp package wp
import ( import (
"fmt"
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
@ -12,7 +13,6 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"strings" "strings"
"sync"
) )
type Handle struct { type Handle struct {
@ -35,10 +35,16 @@ type Handle struct {
abort bool abort bool
componentsArgs map[string]any componentsArgs map[string]any
componentFilterFn map[string][]func(*Handle, string, ...any) string componentFilterFn map[string][]func(*Handle, string, ...any) string
handleCall []HandleCall
} }
var configHandle = reload.Vars(&Handle{}) func (h *Handle) HandleCall() []HandleCall {
var configHandleMux = sync.Mutex{} return h.handleCall
}
func (h *Handle) SetHandleCall(handleCall []HandleCall) {
h.handleCall = handleCall
}
type HandlePlugins map[string]HandleFn[*Handle] type HandlePlugins map[string]HandleFn[*Handle]
@ -60,17 +66,21 @@ type HandleCall struct {
} }
func InitThemeArgAndConfig(fn func(*Handle) *Handle, h *Handle) { func InitThemeArgAndConfig(fn func(*Handle) *Handle, h *Handle) {
hh := configHandle.Load() hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle {
if len(hh.handleFns) < 1 { h.components = make(map[string][]Components[string])
configHandleMux.Lock() h.handleFns = make(map[int][]HandleCall)
hh = configHandle.Load() h.componentsArgs = make(map[string]any)
if len(hh.handleFns) < 1 { h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string)
hh = fn(h) hh := fn(h)
configHandle.Store(hh) 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)
} }
configHandleMux.Unlock() h.components = m // maps.Copy(hh.components)
}
h.components = hh.components
h.handleFns = hh.handleFns h.handleFns = hh.handleFns
h.componentsArgs = hh.componentsArgs h.componentsArgs = hh.componentsArgs
h.componentFilterFn = hh.componentFilterFn h.componentFilterFn = hh.componentFilterFn
@ -200,10 +210,6 @@ func NewHandle(c *gin.Context, scene int, theme string) *Handle {
scene: scene, scene: scene,
Stats: constraints.Ok, Stats: constraints.Ok,
themeMods: mods, 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),
} }
} }
@ -249,8 +255,11 @@ func (h *Handle) PushCacheGroupFooterScript(key string, order int, fns ...func(*
h.PushGroupCacheComponentFn(constraints.FooterScript, key, order, fns...) h.PushGroupCacheComponentFn(constraints.FooterScript, key, order, fns...)
} }
func (h *Handle) PushGroupCacheComponentFn(name, key string, order int, fns ...func(*Handle) string) { func (h *Handle) PushGroupCacheComponentFn(name, key string, order int, fns ...func(*Handle) string) {
v := reload.GetStrBy(key, "\n", h, fns...) h.PushComponents(name, h.NewCacheComponent(key, order, func(h *Handle) string {
h.PushGroupComponentStrs(name, order, v) return strings.Join(slice.Map(fns, func(t func(*Handle) string) string {
return t(h)
}), "\n")
}))
} }
func (h *Handle) GetPassword() { func (h *Handle) GetPassword() {
@ -360,7 +369,7 @@ func CalComponents(h *Handle) {
if component.Fn != nil { if component.Fn != nil {
v := "" v := ""
if component.CacheKey != "" { if component.CacheKey != "" {
v = reload.GetAnyValBys(component.CacheKey, h, component.Fn) v = reload.SafetyMapBy("calComponent", component.CacheKey, h, component.Fn)
} else { } else {
v = component.Fn(h) v = component.Fn(h)
} }
@ -386,6 +395,42 @@ func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
}, initial) }, 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) { func Render(h *Handle) {
switch h.scene { switch h.scene {
case constraints.Detail: case constraints.Detail: