fix bug and optimize code

This commit is contained in:
xing 2024-01-21 21:29:36 +08:00
parent 65bfccdd48
commit 4842d53316
12 changed files with 231 additions and 115 deletions

View File

@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"github.com/fthvgb1/wp-go/app/cmd/route"
"github.com/fthvgb1/wp-go/app/mail"
"github.com/fthvgb1/wp-go/app/pkg/cache"
"github.com/fthvgb1/wp-go/app/pkg/config"
@ -11,6 +10,7 @@ import (
"github.com/fthvgb1/wp-go/app/pkg/logs"
"github.com/fthvgb1/wp-go/app/plugins"
"github.com/fthvgb1/wp-go/app/plugins/wphandle"
"github.com/fthvgb1/wp-go/app/route"
"github.com/fthvgb1/wp-go/app/theme"
"github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/cachemanager"
@ -117,7 +117,7 @@ func reloads() {
err = wpconfig.InitTerms()
logs.IfError(err, "获取WpTerms表失败")
wphandle.LoadPlugins()
reload.Reload()
reload.Reloads("themeArgAndConfig")
flushCache()
log.Println("reload complete")
}

111
app/cmd/sitetest/main.go Normal file
View File

@ -0,0 +1,111 @@
package main
import (
"flag"
"fmt"
"github.com/fthvgb1/wp-go/helper/httptool"
strings2 "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/safety"
"github.com/fthvgb1/wp-go/taskPools"
"net/http"
"os"
"regexp"
"strings"
"sync"
)
var reg = regexp.MustCompile(`<a.*href="([^"]+?)".*?>`)
var m = safety.NewMap[string, bool]()
var mut = sync.Mutex{}
func parseHtml(ss string) {
r := reg.FindAllStringSubmatch(ss, -1)
for _, href := range r {
if href[1] == "/" {
continue
}
if strings.ContainsAny(href[1], ".") {
continue
}
if string([]rune(href[1])[0:3]) == "http" {
continue
}
mut.Lock()
if _, ok := m.Load(href[1]); !ok {
m.Store(href[1], false)
}
mut.Unlock()
}
}
func siteFetch(c int, u string) {
u = strings.TrimRight(u, "/")
ss, code, err := httptool.GetString(u, nil)
if err != nil || code != http.StatusOK {
panic(err)
}
parseHtml(ss)
p := taskPools.NewPools(c)
for {
m.Range(func(key string, value bool) bool {
if value {
return true
}
u := strings2.Join(u, key)
p.Execute(func() {
ss, code, err := httptool.GetString(u, nil)
fmt.Println(u, code)
if err != nil || code != http.StatusOK {
panic(err)
return
}
parseHtml(ss)
m.Store(key, true)
})
return true
})
var x bool
m.Range(func(key string, value bool) bool {
if !value {
x = true
return false
}
return true
})
if !x {
break
}
}
p.Wait()
m.Flush()
}
var c int
var u string
var t int
func main() {
flag.IntVar(&c, "c", 10, "concurrency num")
flag.StringVar(&u, "url", "http://127.0.0.1:8081", "test url")
flag.IntVar(&t, "t", 1, "request full site times")
flag.Parse()
if u == "" {
fmt.Println("url can't emtpy")
os.Exit(2)
}
if c < 1 {
fmt.Println("concurrency num must >= 1")
os.Exit(2)
}
if t < 1 {
for {
siteFetch(c, u)
}
}
for i := 0; i < t; i++ {
siteFetch(c, u)
}
}

View File

@ -25,6 +25,9 @@ var comFn = template.FuncMap{
"exec": func(fn func() string) template.HTML {
return template.HTML(fn())
},
"callFuncString": func(fn func(string) string, s string) template.HTML {
return template.HTML(fn(s))
},
}
func postsFn(fn func(models.Posts) string, a models.Posts) string {

View File

@ -3,11 +3,13 @@ package twentyfifteen
import (
"github.com/fthvgb1/wp-go/app/pkg/constraints"
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
"github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/app/plugins"
"github.com/fthvgb1/wp-go/app/theme/wp"
"github.com/fthvgb1/wp-go/app/theme/wp/components"
"github.com/fthvgb1/wp-go/app/theme/wp/middleware"
"github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/reload"
"strings"
)
@ -28,7 +30,7 @@ func configs(h *wp.Handle) {
h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss)
h.CommonComponents()
components.WidgetArea(h)
h.SetData("customHeader", customHeader(h))
h.PushRender(constraints.AllScene, wp.NewHandleFn(renderCustomHeader, 20.5, "renderCustomHeader"))
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(wp.IndexRender, 50.005, "wp.IndexRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50.005, "wp.DetailRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60.005, "postThumb"))
@ -54,6 +56,16 @@ func setPaginationAndRender(h *wp.Handle) {
func postThumb(h *wp.Handle) {
d := h.GetDetailHandle()
if d.Post.Thumbnail.Path != "" {
d.Post.Thumbnail = wpconfig.Thumbnail(d.Post.Thumbnail.OriginAttachmentData, "post-thumbnail", "")
d.Post.Thumbnail = getPostThumbs(d.Post.Id, d.Post)
}
}
var getPostThumbs = reload.BuildMapFn[uint64]("twentyFifteen-post-thumbnail", postThumbs)
func postThumbs(post models.Posts) models.PostThumbnail {
return wpconfig.Thumbnail(post.Thumbnail.OriginAttachmentData, "post-thumbnail", "")
}
func renderCustomHeader(h *wp.Handle) {
h.SetData("customHeader", customHeader(h))
}

View File

@ -112,13 +112,19 @@ func errorsHandle(h *wp.Handle) {
func postThumb(h *wp.Handle) {
d := h.GetDetailHandle()
if d.Post.Thumbnail.Path != "" {
img := wpconfig.Thumbnail(d.Post.Thumbnail.OriginAttachmentData, "full", "", "thumbnail", "post-thumbnail")
img.Sizes = "100vw"
img.Srcset = fmt.Sprintf("%s %dw, %s", img.Path, img.Width, img.Srcset)
d.Post.Thumbnail = img
d.Post.Thumbnail = getPostThumbs(d.Post.Id, d.Post)
}
}
var getPostThumbs = reload.BuildMapFn[uint64]("post-thumbnail", postThumbs)
func postThumbs(post models.Posts) models.PostThumbnail {
img := wpconfig.Thumbnail(post.Thumbnail.OriginAttachmentData, "full", "", "thumbnail", "post-thumbnail")
img.Sizes = "100vw"
img.Srcset = fmt.Sprintf("%s %dw, %s", img.Path, img.Width, img.Srcset)
return img
}
var commentFormat = comment{}
type comment struct {

View File

@ -11,52 +11,59 @@ import (
)
var handleComponents = safety.NewMap[string, map[string][]Components[string]]()
var handleComponentHook = safety.NewMap[string, []func(Components[string]) (Components[string], bool)]()
var handleComponentHook = safety.NewMap[string, map[string][]func(Components[string]) (Components[string], bool)]()
var componentsArgs = safety.NewMap[string, any]()
var componentFilterFns = safety.NewMap[string, []func(*Handle, string, ...any) string]()
func (h *Handle) DeleteComponents(scene, name string) {
v, _ := handleComponentHook.Load(scene)
v = append(v, func(c Components[string]) (Components[string], bool) {
return c, c.Name != name
func (h *Handle) DeleteComponents(scene, componentKey, componentName string) {
v, ok := handleComponentHook.Load(scene)
if !ok {
v = make(map[string][]func(Components[string]) (Components[string], bool))
}
v[componentKey] = append(v[componentKey], func(c Components[string]) (Components[string], bool) {
return c, c.Name != componentName
})
handleComponentHook.Store(scene, v)
}
func (h *Handle) ReplaceComponents(scene, name string, components Components[string]) {
v, _ := handleComponentHook.Load(scene)
v = append(v, func(c Components[string]) (Components[string], bool) {
if c.Name == name {
func (h *Handle) ReplaceComponents(scene, componentKey, componentName string, components Components[string]) {
v, ok := handleComponentHook.Load(scene)
if !ok {
v = make(map[string][]func(Components[string]) (Components[string], bool))
}
v[componentKey] = append(v[componentKey], func(c Components[string]) (Components[string], bool) {
if c.Name == componentName {
c = components
}
return c, true
})
handleComponentHook.Store(scene, v)
}
func (h *Handle) HookComponents(scene string, fn func(Components[string]) (Components[string], bool)) {
v, _ := handleComponentHook.Load(scene)
v = append(v, fn)
func (h *Handle) PushComponentHooks(scene, componentKey string, fn func(Components[string]) (Components[string], bool)) {
v, ok := handleComponentHook.Load(scene)
if !ok {
v = make(map[string][]func(Components[string]) (Components[string], bool))
}
v[componentKey] = append(v[componentKey], fn)
handleComponentHook.Store(scene, v)
}
var GetComponents = reload.BuildMapFn[string]("scene-components", getComponent)
var HookComponents = reload.BuildMapFnWithAnyParams[string]("calComponents", hookComponent)
var GetAndHookComponents = reload.BuildMapFnWithAnyParams[string]("calComponents", HookComponent)
func hookComponent(a ...any) []Components[string] {
k := a[0].(string)
components := a[1].([]Components[string])
func HookComponent(a ...any) []Components[string] {
componentKey := a[0].(string)
scene := a[1].(string)
mut := reload.GetGlobeMutex()
mut.Lock()
allHooks := slice.FilterAndToMap(components, func(t Components[string], _ int) (string, []func(Components[string]) (Components[string], bool), bool) {
fn, ok := handleComponentHook.Load(k)
return k, fn, ok
})
mut.Unlock()
defer mut.Unlock()
components := GetComponents(scene, componentKey)
r := slice.FilterAndMap(components, func(component Components[string]) (Components[string], bool) {
hooks, ok := allHooks[k]
keyHooks, ok := handleComponentHook.Load(scene)
if !ok {
return component, true
}
hooks := keyHooks[componentKey]
for _, fn := range hooks {
hookedComponent, ok := fn(component)
if !ok { // DeleteComponents fn
@ -72,35 +79,23 @@ func hookComponent(a ...any) []Components[string] {
return r
}
func getComponent(h *Handle) map[string][]Components[string] {
mut := reload.GetGlobeMutex()
mut.Lock()
sceneComponents, _ := handleComponents.Load(h.scene)
func GetComponents(scene, key string) (r []Components[string]) {
sceneComponents, _ := handleComponents.Load(scene)
allSceneComponents, _ := handleComponents.Load(constraints.AllScene)
mut.Unlock()
return maps.MergeBy(func(k string, c1, c2 []Components[string]) ([]Components[string], bool) {
vv := append(c1, c2...)
return vv, vv != nil
}, nil, sceneComponents, allSceneComponents)
r = append(sceneComponents[key], allSceneComponents[key]...)
return
}
type cacheComponentParm[T any] struct {
Components[T]
h *Handle
var CacheComponent = reload.BuildMapFnWithAnyParams[string]("cacheComponents", cacheComponentFn)
func cacheComponentFn(a ...any) string {
return a[0].(Components[string]).Fn(a[1].(*Handle))
}
var cacheComponentsFn = reload.BuildMapFn[string]("cacheComponents", cacheComponentFn)
func cacheComponentFn(a cacheComponentParm[string]) string {
return a.Fn(a.h)
}
func CalComponents(h *Handle) {
allComponents := GetComponents(str.Join("allScene-", h.scene), h)
for k, components := range allComponents {
key := str.Join("calComponents-", h.theme, "-", h.scene, "-", k)
hookedComponents := HookComponents(key, k, components)
func CalComponent(h *Handle) func(string) string {
return func(componentKey string) string {
cacheKey := str.Join("get-hook-Components-", h.scene, "-", componentKey)
hookedComponents := GetAndHookComponents(cacheKey, componentKey, h.scene)
var s = make([]string, 0, len(hookedComponents))
for _, component := range hookedComponents {
if component.Val != "" {
@ -110,7 +105,8 @@ func CalComponents(h *Handle) {
if component.Fn != nil {
v := ""
if component.Cached {
v = cacheComponentsFn(component.Name, cacheComponentParm[string]{component, h})
key := str.Join(h.scene, "-", componentKey, "-", component.Name)
v = CacheComponent(key, component, h)
} else {
v = component.Fn(h)
}
@ -119,7 +115,7 @@ func CalComponents(h *Handle) {
}
}
}
h.ginH[k] = strings.Join(s, "\n")
return strings.Join(s, "\n")
}
}

View File

@ -41,7 +41,7 @@ var archivesConfig = map[any]any{
}
var GetArchiveConf = BuildconfigFn(archivesConfig, "widget_archives", int64(2))
var GetArchiveArgs = reload.BuildValFnWithAnyParams("", archiveArgsFn)
var GetArchiveArgs = reload.BuildValFnWithAnyParams("widget_archive-args", archiveArgsFn)
func archiveArgsFn(a ...any) map[string]string {
h := a[0].(*wp.Handle)

View File

@ -1,8 +1,6 @@
{{define "common/head"}}
{{if .headScript}}
{{.headScript|unescaped}}
{{end}}
{{ callFuncString .calComponent "headScript"}}
{{if .externHead}}
{{.externHead|unescaped}}
@ -10,9 +8,7 @@
{{end}}
{{define "common/footer"}}
{{if .footerScript}}
{{.footerScript|unescaped}}
{{end}}
{{ callFuncString .calComponent "footerScript"}}
{{if .externFooter}}
{{.externFooter|unescaped}}
{{end}}
@ -20,9 +16,7 @@
{{define "common/sidebarWidget"}}
{{if .sidebarsWidgets}}
{{.sidebarsWidgets|unescaped}}
{{end}}
{{ callFuncString .calComponent "sidebarsWidgets"}}
{{end}}
{{define "common/colophon"}}

View File

@ -56,7 +56,7 @@ func (h *Handle) Components() *safety.Map[string, map[string][]Components[string
return handleComponents
}
func (h *Handle) ComponentHook() *safety.Map[string, []func(Components[string]) (Components[string], bool)] {
func (h *Handle) ComponentHook() *safety.Map[string, map[string][]func(Components[string]) (Components[string], bool)] {
return handleComponentHook
}
@ -99,9 +99,6 @@ func SetConfigHandle(a ...any) Handle {
configFn := a[0].(func(*Handle))
hh := a[1].(*Handle)
h := &Handle{}
mut := reload.GetGlobeMutex()
mut.Lock()
defer mut.Unlock()
handleComponents.Flush()
componentsArgs.Flush()
handleComponentHook.Flush()
@ -120,10 +117,11 @@ func SetConfigHandle(a ...any) Handle {
if ok {
pluginFn(h)
}
reload.Reload()
return *h
}
var GetInitHandleFn = reload.BuildValFnWithAnyParams("themeArgAndConfig", SetConfigHandle, 100.01)
var GetInitHandleFn = reload.BuildValFnWithAnyParams("themeArgAndConfig", SetConfigHandle, false)
type ConfigParm struct {
ConfigFn func(*Handle)
@ -136,6 +134,7 @@ func InitHandle(configFn func(*Handle), h *Handle) {
h.ginH["calPostClass"] = postClass(h)
h.ginH["calBodyClass"] = bodyClass(h)
h.ginH["customLogo"] = customLogo(h)
h.ginH["calComponent"] = CalComponent(h)
h.isInited = true
}
@ -246,7 +245,6 @@ func (h *Handle) PushHandlers(pipeScene string, call HandleCall, statsOrScene ..
func (h *Handle) CommonComponents() {
h.PushCacheGroupHeadScript(constraints.AllScene, "siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss)
h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10.001, "wp.CalComponents"))
h.PushRender(constraints.AllStats, NewHandleFn(PreRenderTemplate, 0, "wp.PreRenderTemplate"))
ReplyCommentJs(h)
AdditionScript(h)

View File

@ -61,7 +61,9 @@ func DeleteMapVal[T any](namespace string, key ...T) {
fn(key)
}
func Specifies(namespaces ...string) {
func Reloads(namespaces ...string) {
mut.Lock()
defer mut.Unlock()
for _, namespace := range namespaces {
fn, ok := callMap.Load(namespace)
if !ok {
@ -93,7 +95,7 @@ func BuildMapFnWithConfirm[K comparable, V, A any](namespace string, fn func(A)
}
}
// BuildMapFn build given fn with a new fn which returned value can be saved and flushed when called Reload or Specifies
// BuildMapFn build given fn with a new fn which returned value can be saved and flushed when called Reload or Reloads
// with namespace
//
// if give a float then can be reloaded early or lately, more bigger more earlier
@ -153,8 +155,7 @@ func BuildSafetyMap[K comparable, V, A any](namespace string, args ...any) *Safe
return m
}
m = &SafetyMap[K, V, A]{safety.NewMap[K, V](), sync.Mutex{}}
ord, _ := parseArgs(args...)
autoFlush := helper.ParseArgs(true, args...)
args = append(args, namespace)
deleteMapFn.Store(namespace, func(a any) {
k, ok := a.([]K)
if !ok && len(k) > 0 {
@ -164,13 +165,8 @@ func BuildSafetyMap[K comparable, V, A any](namespace string, args ...any) *Safe
m.Val.Delete(key)
}
})
if autoFlush {
Push(func() {
m.Val.Flush()
}, ord, namespace)
}
Push(m.Val.Flush, args...)
safetyMaps.Store(namespace, m)
return m
}
@ -198,22 +194,19 @@ func BuildAnyVal[T, A any](namespace string, counter bool, args ...any) *SafetyV
vvv, ok := safetyMaps.Load(namespace)
if ok {
vv = vvv.(*SafetyVar[T, A])
} else {
safetyMapLock.Lock()
defer safetyMapLock.Unlock()
vvv, ok = safetyMaps.Load(namespace)
if ok {
vv = vvv.(*SafetyVar[T, A])
} else {
v := Val[T]{}
vv = &SafetyVar[T, A]{safety.NewVar(v), sync.Mutex{}}
ord, _ := parseArgs(args...)
Push(func() {
vv.Val.Flush()
}, ord, namespace)
safetyMaps.Store(namespace, vv)
}
}
safetyMapLock.Lock()
defer safetyMapLock.Unlock()
vvv, ok = safetyMaps.Load(namespace)
if ok {
vv = vvv.(*SafetyVar[T, A])
return vv
}
v := Val[T]{}
vv = &SafetyVar[T, A]{safety.NewVar(v), sync.Mutex{}}
args = append(args, namespace)
Push(vv.Val.Flush, args...)
safetyMaps.Store(namespace, vv)
return vv
}
@ -272,14 +265,14 @@ func BuildValFnWithConfirm[T, A any](namespace string, fn func(A) (T, bool), arg
}
}
// BuildValFn build given fn a new fn which return value can be saved and flushed when called Reload or Specifies
// BuildValFn build given fn a new fn which return value can be saved and flushed when called Reload or Reloads
// with namespace.
//
// note: namespace should be not same as BuildMapFn and related fn, they stored same safety.Map[string,any].
//
// if give a float then can be reloaded early or lately, more bigger more earlier
//
// if give a bool false will not flushed when called Reload, then can called GetValMap to flush manually
// if give a bool false will not flushed when called Reload, but can call GetValMap or Reloads to flush manually
func BuildValFn[T, A any](namespace string, fn func(A) T, args ...any) func(A) T {
var vv = BuildAnyVal[T, A](namespace, false, args...)
return func(a A) T {
@ -325,15 +318,17 @@ func BuildValFnWithAnyParams[T any](namespace string, fn func(...any) T, args ..
//
// args same as Push
//
// if give a name, then can be flushed by calls Specifies
// if give a name, then can be flushed by calls Reloads
//
// if give a float then can be reloaded early or lately, more bigger more earlier
//
// if give a bool false will not flushed when called Reload, but can call GetValMap or Reloads to flush manually
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)
}, args...)
return ss
}
@ -356,13 +351,12 @@ func parseArgs(a ...any) (ord float64, name string) {
// VarsBy
//
// args same as Push
// if give a name, then can be flushed by calls Specifies
// if give a name, then can be flushed by calls Reloads
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)
}, args...)
return ss
}
func MapBy[K comparable, T any](fn func(*safety.Map[K, T]), args ...any) *safety.Map[K, T] {
@ -370,32 +364,35 @@ func MapBy[K comparable, T any](fn func(*safety.Map[K, T]), args ...any) *safety
if fn != nil {
fn(m)
}
ord, name := parseArgs(args...)
Push(func() {
m.Flush()
if fn != nil {
fn(m)
}
}, ord, name)
}, args...)
return m
}
func SafeMap[K comparable, T any](args ...any) *safety.Map[K, T] {
m := safety.NewMap[K, T]()
ord, name := parseArgs(args...)
Push(func() {
m.Flush()
}, ord, name)
Push(m.Flush, args...)
return m
}
// Push the func that will be called whenever Reload called
//
// if give a name, then can be called by called Specifies
// if give a name, then can be called by called Reloads
//
// if give a float then can be called early or lately when called Reload, more bigger more earlier
//
// if give a bool false will not flushed when called Reload, then can called GetValMap to flush manually
func Push(fn func(), a ...any) {
ord, name := parseArgs(a...)
auto := helper.ParseArgs(true, a...)
if name != "" && !auto {
callMap.Store(name, fn)
return
}
waitReloadCalls.Append(queue{fn, ord, name})
if name != "" {
callMap.Store(name, fn)
@ -405,7 +402,6 @@ func Push(fn func(), a ...any) {
func Reload() {
mut.Lock()
defer mut.Unlock()
callMap.Flush()
deleteMapFn.Flush()
reloadCalls := waitReloadCalls.Load()
slice.SimpleSort(reloadCalls, slice.DESC, func(t queue) float64 {

View File

@ -20,7 +20,7 @@ func TestFlushMapVal(t *testing.T) {
return 33, true
})
fmt.Println(v)
Specifies("key")
Reloads("key")
v = GetAnyValMapBy[int, int, struct{}]("key", 2, struct{}{}, func(a struct{}) (int, bool) {
fmt.Println("yyyy")
return 33, true