optimize sign mechanism
This commit is contained in:
parent
dcbe760f09
commit
9c60d10568
|
@ -3,7 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/mail"
|
"github.com/fthvgb1/wp-go/app/ossigns"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/db"
|
"github.com/fthvgb1/wp-go/app/pkg/db"
|
||||||
|
@ -14,14 +14,10 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/theme"
|
"github.com/fthvgb1/wp-go/app/theme"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/cache/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -89,52 +85,6 @@ func cronClearCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func flushCache() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
err := mail.SendMail([]string{config.GetConfig().Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r))
|
|
||||||
logs.IfError(err, "发邮件失败")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
cachemanager.Flush()
|
|
||||||
log.Println("all cache flushed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func reloads() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
log.Println(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
err := config.InitConfig(confPath)
|
|
||||||
logs.IfError(err, "获取配置文件失败", confPath)
|
|
||||||
err = logs.InitLogger()
|
|
||||||
logs.IfError(err, "日志配置错误")
|
|
||||||
_, err = db.InitDb()
|
|
||||||
logs.IfError(err, "重新读取db失败", config.GetConfig().Mysql)
|
|
||||||
err = wpconfig.InitOptions()
|
|
||||||
logs.IfError(err, "获取网站设置WpOption失败")
|
|
||||||
err = wpconfig.InitTerms()
|
|
||||||
logs.IfError(err, "获取WpTerms表失败")
|
|
||||||
wphandle.LoadPlugins()
|
|
||||||
reload.Reloads("themeArgAndConfig")
|
|
||||||
flushCache()
|
|
||||||
log.Println("reload complete")
|
|
||||||
}
|
|
||||||
|
|
||||||
func signalNotify() {
|
|
||||||
c := make(chan os.Signal)
|
|
||||||
signal.Notify(c, syscall.SIGUSR1, syscall.SIGUSR2)
|
|
||||||
for {
|
|
||||||
switch <-c {
|
|
||||||
case syscall.SIGUSR1:
|
|
||||||
go reloads()
|
|
||||||
case syscall.SIGUSR2:
|
|
||||||
go flushCache()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
@ -143,7 +93,8 @@ func main() {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
inits()
|
inits()
|
||||||
go signalNotify()
|
ossigns.SetConfPath(confPath)
|
||||||
|
go ossigns.SignalNotify()
|
||||||
Gin := route.SetupRouter()
|
Gin := route.SetupRouter()
|
||||||
c := config.GetConfig()
|
c := config.GetConfig()
|
||||||
if c.Ssl.Key != "" && c.Ssl.Cert != "" {
|
if c.Ssl.Key != "" && c.Ssl.Cert != "" {
|
||||||
|
|
69
app/ossigns/sings.go
Normal file
69
app/ossigns/sings.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package ossigns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/mail"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/db"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
|
"github.com/fthvgb1/wp-go/app/plugins/wphandle"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/signs"
|
||||||
|
"log"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var confPath string
|
||||||
|
|
||||||
|
func SetConfPath(path string) {
|
||||||
|
confPath = path
|
||||||
|
}
|
||||||
|
|
||||||
|
func FlushCache() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err := mail.SendMail([]string{config.GetConfig().Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r))
|
||||||
|
logs.IfError(err, "发邮件失败")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cachemanager.Flush()
|
||||||
|
log.Println("all cache flushed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reloads() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.Println(r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err := config.InitConfig(confPath)
|
||||||
|
logs.IfError(err, "获取配置文件失败", confPath)
|
||||||
|
err = logs.InitLogger()
|
||||||
|
logs.IfError(err, "日志配置错误")
|
||||||
|
_, err = db.InitDb()
|
||||||
|
logs.IfError(err, "重新读取db失败", config.GetConfig().Mysql)
|
||||||
|
err = wpconfig.InitOptions()
|
||||||
|
logs.IfError(err, "获取网站设置WpOption失败")
|
||||||
|
err = wpconfig.InitTerms()
|
||||||
|
logs.IfError(err, "获取WpTerms表失败")
|
||||||
|
wphandle.LoadPlugins()
|
||||||
|
reload.Reloads("themeArgAndConfig")
|
||||||
|
FlushCache()
|
||||||
|
log.Println("reload complete")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignalNotify() {
|
||||||
|
rel := func() bool {
|
||||||
|
go Reloads()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
flu := func() bool {
|
||||||
|
go FlushCache()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
signs.Install(syscall.SIGUSR1, rel, "reload")
|
||||||
|
signs.Install(syscall.SIGUSR2, flu, "flush")
|
||||||
|
signs.Wait()
|
||||||
|
}
|
|
@ -153,12 +153,20 @@ func SetBody(req *http.Request, types int, form map[string]any) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bb, ok := maps.GetStrAnyVal[*[]byte](form, "binary")
|
bb, ok := maps.GetStrAnyVal[*[]byte](form, "binary")
|
||||||
if !ok {
|
if ok {
|
||||||
return errors.New("no binary value")
|
req.Body = io.NopCloser(NewBodyBuffer(bb))
|
||||||
}
|
|
||||||
req.Body = io.NopCloser(&BodyBuffer{0, bb})
|
|
||||||
req.Header.Add("Content-Type", "application/octet-stream")
|
req.Header.Add("Content-Type", "application/octet-stream")
|
||||||
req.ContentLength = int64(len(*bb))
|
req.ContentLength = int64(len(*bb))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bf, ok := maps.GetStrAnyVal[*BodyBuffer](form, "binary")
|
||||||
|
if ok {
|
||||||
|
req.Body = bf
|
||||||
|
req.Header.Add("Content-Type", "application/octet-stream")
|
||||||
|
req.ContentLength = int64(len(*bf.Data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return errors.New("no binary value")
|
||||||
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -167,32 +175,23 @@ func SetBody(req *http.Request, types int, form map[string]any) (err error) {
|
||||||
type BodyBuffer struct {
|
type BodyBuffer struct {
|
||||||
Offset int
|
Offset int
|
||||||
Data *[]byte
|
Data *[]byte
|
||||||
|
ReadFn func([]byte) (int, error)
|
||||||
|
CloseFn func() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BodyBuffer) Write(p []byte) (int, error) {
|
func (b *BodyBuffer) Close() error {
|
||||||
if b.Offset == 0 {
|
if b.CloseFn != nil {
|
||||||
copy(*b.Data, p)
|
return b.CloseFn()
|
||||||
if len(p) <= len(*b.Data) {
|
|
||||||
b.Offset += len(p)
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
b.Offset += len(*b.Data)
|
b.Offset = 0
|
||||||
return len(*b.Data), nil
|
return nil
|
||||||
}
|
|
||||||
if len(p)+b.Offset <= len(*b.Data) {
|
|
||||||
copy((*b.Data)[b.Offset:b.Offset+len(p)], p)
|
|
||||||
b.Offset += len(p)
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
l := len(*b.Data) - b.Offset
|
|
||||||
if l <= 0 {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
copy((*b.Data)[b.Offset:], p[:l])
|
|
||||||
return l, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BodyBuffer) Read(p []byte) (int, error) {
|
func (b *BodyBuffer) Read(p []byte) (int, error) {
|
||||||
|
return b.ReadFn(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BodyBuffer) Reads(p []byte) (int, error) {
|
||||||
data := (*b.Data)[b.Offset:]
|
data := (*b.Data)[b.Offset:]
|
||||||
if len(p) <= len(data) {
|
if len(p) <= len(data) {
|
||||||
copy(p, data[0:len(p)])
|
copy(p, data[0:len(p)])
|
||||||
|
@ -208,8 +207,18 @@ func (b *BodyBuffer) Read(p []byte) (int, error) {
|
||||||
return len(data), io.EOF
|
return len(data), io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBodyBuffer(bytes *[]byte) BodyBuffer {
|
func NewBodyBuffer(byt *[]byte, readFn ...func(*BodyBuffer, []byte) (int, error)) *BodyBuffer {
|
||||||
return BodyBuffer{0, bytes}
|
var fn func([]byte) (int, error)
|
||||||
|
b := &BodyBuffer{Data: byt}
|
||||||
|
if len(readFn) > 1 {
|
||||||
|
fn = func(p []byte) (int, error) {
|
||||||
|
return readFn[0](b, p)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fn = b.Reads
|
||||||
|
}
|
||||||
|
b.ReadFn = fn
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostClient(u string, types int, form map[string]any, a ...any) (cli *http.Client, req *http.Request, err error) {
|
func PostClient(u string, types int, form map[string]any, a ...any) (cli *http.Client, req *http.Request, err error) {
|
||||||
|
|
|
@ -42,3 +42,6 @@ func (q *Map[K, T]) Del(name K) {
|
||||||
slice.Delete((*[]Item[K, T])(q), i)
|
slice.Delete((*[]Item[K, T])(q), i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (q *Map[K, T]) DelByIndex(i int) {
|
||||||
|
slice.Delete((*[]Item[K, T])(q), i)
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,15 @@ func FilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func FilterAndMaps[N any, T any](arr []T, fn func(int, T) (N, bool)) (r []N) {
|
||||||
|
for i, t := range arr {
|
||||||
|
x, ok := fn(i, t)
|
||||||
|
if ok {
|
||||||
|
r = append(r, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Walk[T any](arr []T, fn func(*T)) {
|
func Walk[T any](arr []T, fn func(*T)) {
|
||||||
for i := 0; i < len(arr); i++ {
|
for i := 0; i < len(arr); i++ {
|
||||||
|
|
|
@ -10,8 +10,12 @@ type Var[T any] struct {
|
||||||
p unsafe.Pointer
|
p unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVar[T any](val T) *Var[T] {
|
func NewVar[T any](vals ...T) *Var[T] {
|
||||||
return &Var[T]{val: val, p: unsafe.Pointer(&val)}
|
var v T
|
||||||
|
if len(vals) > 0 {
|
||||||
|
v = vals[0]
|
||||||
|
}
|
||||||
|
return &Var[T]{val: v, p: unsafe.Pointer(&v)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Var[T]) Load() T {
|
func (r *Var[T]) Load() T {
|
||||||
|
|
135
signs/signs.go
Normal file
135
signs/signs.go
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package signs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Call func() bool
|
||||||
|
|
||||||
|
type HookFn func(mockmap.Item[string, Call]) (os.Signal, mockmap.Item[string, Call], bool)
|
||||||
|
|
||||||
|
var queues = map[os.Signal]mockmap.Map[string, Call]{}
|
||||||
|
|
||||||
|
var ch = make(chan os.Signal, 1)
|
||||||
|
|
||||||
|
var stopCh = make(chan struct{}, 1)
|
||||||
|
|
||||||
|
var hooks = map[os.Signal][]HookFn{}
|
||||||
|
|
||||||
|
var mux = sync.Mutex{}
|
||||||
|
|
||||||
|
func GetChannel() chan os.Signal {
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cancel(sings ...os.Signal) {
|
||||||
|
if len(sings) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
for _, sing := range sings {
|
||||||
|
delete(queues, sing)
|
||||||
|
}
|
||||||
|
signal.Reset(sings...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Hook(sign os.Signal, fn HookFn) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
hooks[sign] = append(hooks[sign], fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hook(item []mockmap.Item[string, Call], sign os.Signal) []mockmap.Item[string, Call] {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
if len(item) < 1 {
|
||||||
|
delete(hooks, sign)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
hooksFn, ok := hooks[sign]
|
||||||
|
if !ok {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
for _, fn := range hooksFn {
|
||||||
|
item = slice.FilterAndMap(item, func(t mockmap.Item[string, Call]) (mockmap.Item[string, Call], bool) {
|
||||||
|
s, c, ok := fn(t)
|
||||||
|
if sign != s {
|
||||||
|
install(s, t.Value, t.Name, t.Order)
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
return c, ok
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
delete(hooks, sign)
|
||||||
|
slice.SimpleSort(item, slice.DESC, func(t mockmap.Item[string, Call]) float64 {
|
||||||
|
return t.Order
|
||||||
|
})
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
func Install(sign os.Signal, fn Call, a ...any) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
arr := helper.ParseArgs([]os.Signal{}, a...)
|
||||||
|
if len(arr) > 0 {
|
||||||
|
for _, o := range arr {
|
||||||
|
install(o, fn, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
install(sign, fn, a...)
|
||||||
|
}
|
||||||
|
func install(sign os.Signal, fn Call, a ...any) {
|
||||||
|
m, ok := queues[sign]
|
||||||
|
if !ok {
|
||||||
|
queues[sign] = make(mockmap.Map[string, Call], 0)
|
||||||
|
signal.Notify(ch, sign)
|
||||||
|
}
|
||||||
|
m.Set(helper.ParseArgs("", a...), fn, helper.ParseArgs[float64](0, a...))
|
||||||
|
queues[sign] = m
|
||||||
|
}
|
||||||
|
|
||||||
|
func del(queue mockmap.Map[string, Call], sign os.Signal, i int) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
queue.DelByIndex(i)
|
||||||
|
queues[sign] = queue
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop() {
|
||||||
|
stopCh <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Wait() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
break
|
||||||
|
case sign := <-ch:
|
||||||
|
queue, ok := queues[sign]
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
queue = hook(queue, sign)
|
||||||
|
queues[sign] = queue
|
||||||
|
if len(queue) < 1 {
|
||||||
|
signal.Reset(sign)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i, item := range queue {
|
||||||
|
if !item.Value() {
|
||||||
|
del(queue, sign, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(queues[sign]) < 1 {
|
||||||
|
signal.Reset(sign)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user