fix(core): optimize ioc interface caching, event parallel timeout and router teardown reversibility

This commit is contained in:
ryan
2026-09-03 09:09:33 +08:00
parent 30ab8810cc
commit 2124bce7ca
7 changed files with 255 additions and 31 deletions
+15 -1
View File
@@ -379,7 +379,7 @@ func TestContextExtensionPointsIntegration(t *testing.T) {
func TestExtensionPointsUnregister(t *testing.T) {
ctx := core.NewContext(context.Background())
// 1. Router unregister
// 1. Router unregister (routes, middlewares, whitelist)
rd := ctx.Router().GET("/temp", "temp_handler")
assert.Greater(t, rd.ID, uint64(0))
assert.Len(t, ctx.Router().Routes(), 1)
@@ -391,6 +391,20 @@ func TestExtensionPointsUnregister(t *testing.T) {
assert.True(t, ctx.Router().UnregisterByID(rd2.ID))
assert.Len(t, ctx.Router().Routes(), 0)
ctx.Router().Use("mw1")
assert.Len(t, ctx.Router().Middlewares(), 1)
if reg, ok := ctx.Router().(*extpoints.RouterRegistry); ok {
ids := reg.UseWithID("mw2")
assert.Len(t, ctx.Router().Middlewares(), 2)
assert.True(t, ctx.Router().UnregisterMiddlewareByID(ids[0]))
assert.Len(t, ctx.Router().Middlewares(), 1)
}
ctx.Router().RegisterWhitelist("/api/v1/temp/*")
assert.True(t, ctx.Router().IsWhitelisted("/api/v1/temp/item"))
ctx.Router().UnregisterWhitelist("/api/v1/temp/*")
assert.False(t, ctx.Router().IsWhitelisted("/api/v1/temp/item"))
// 2. Task unregister
ctx.Task().Register("temp:task", "handler")
assert.Len(t, ctx.Task().Tasks(), 1)
+84 -6
View File
@@ -39,17 +39,26 @@ type RouterExtension interface {
Middlewares() []any
Unregister(method, path string) bool
UnregisterByID(id uint64) bool
UnregisterMiddlewareByID(id uint64) bool
RegisterWhitelist(patterns ...string)
UnregisterWhitelist(patterns ...string)
Whitelist() []string
IsWhitelisted(path string) bool
}
// middlewareDefinition holds an assigned ID and handler for registered middleware.
type middlewareDefinition struct {
ID uint64
Handler any
}
// RouterRegistry implements RouterExtension as the root route and middleware collector.
type RouterRegistry struct {
mu sync.RWMutex
nextID uint64
nextMWID uint64
routes []RouteDefinition
middlewares []any
middlewares []middlewareDefinition
whitelist PathWhitelist
}
@@ -60,17 +69,48 @@ func NewRouterRegistry() *RouterRegistry {
// Use registers global middlewares to the router.
func (r *RouterRegistry) Use(middlewares ...any) {
r.mu.Lock()
defer r.mu.Unlock()
r.middlewares = append(r.middlewares, middlewares...)
r.UseWithID(middlewares...)
}
// Middlewares returns a copy of registered root middlewares.
// UseWithID registers global middlewares to the router and returns their assigned IDs.
func (r *RouterRegistry) UseWithID(middlewares ...any) []uint64 {
r.mu.Lock()
defer r.mu.Unlock()
ids := make([]uint64, 0, len(middlewares))
for _, mw := range middlewares {
r.nextMWID++
r.middlewares = append(r.middlewares, middlewareDefinition{
ID: r.nextMWID,
Handler: mw,
})
ids = append(ids, r.nextMWID)
}
return ids
}
// UnregisterMiddlewareByID removes a registered global middleware by its unique ID.
func (r *RouterRegistry) UnregisterMiddlewareByID(id uint64) bool {
r.mu.Lock()
defer r.mu.Unlock()
for i, mw := range r.middlewares {
if mw.ID == id {
r.middlewares = append(r.middlewares[:i], r.middlewares[i+1:]...)
return true
}
}
return false
}
// Middlewares returns a copy of registered root middleware handlers.
func (r *RouterRegistry) Middlewares() []any {
r.mu.RLock()
defer r.mu.RUnlock()
res := make([]any, len(r.middlewares))
copy(res, r.middlewares)
for i, mw := range r.middlewares {
res[i] = mw.Handler
}
return res
}
@@ -196,6 +236,11 @@ func (r *RouterRegistry) RegisterWhitelist(patterns ...string) {
r.whitelist.Add(patterns...)
}
// UnregisterWhitelist removes path patterns from the whitelist.
func (r *RouterRegistry) UnregisterWhitelist(patterns ...string) {
r.whitelist.Remove(patterns...)
}
// Whitelist returns a copy of all registered whitelist path patterns.
func (r *RouterRegistry) Whitelist() []string {
return r.whitelist.Patterns()
@@ -267,6 +312,11 @@ func (g *RouterGroup) UnregisterByID(id uint64) bool {
return g.registry.UnregisterByID(id)
}
// UnregisterMiddlewareByID removes a middleware by ID via the root registry.
func (g *RouterGroup) UnregisterMiddlewareByID(id uint64) bool {
return g.registry.UnregisterMiddlewareByID(id)
}
// GET registers a GET route in this group.
func (g *RouterGroup) GET(path string, handlers ...any) RouteDefinition {
return g.Handle("GET", path, handlers...)
@@ -331,6 +381,13 @@ func (g *RouterGroup) RegisterWhitelist(patterns ...string) {
}
}
// UnregisterWhitelist removes path patterns under this group prefix from the whitelist.
func (g *RouterGroup) UnregisterWhitelist(patterns ...string) {
for _, p := range patterns {
g.registry.UnregisterWhitelist(joinPaths(g.prefix, p))
}
}
// Whitelist returns a copy of all registered whitelist path patterns.
func (g *RouterGroup) Whitelist() []string {
return g.registry.Whitelist()
@@ -465,6 +522,27 @@ func (w *PathWhitelist) Replace(patterns ...string) {
w.patterns = compiled
}
// Remove removes matching patterns from the whitelist.
func (w *PathWhitelist) Remove(patterns ...string) {
if len(patterns) == 0 {
return
}
targets := make(map[string]struct{}, len(patterns))
for _, p := range patterns {
targets[cleanPath(p)] = struct{}{}
}
w.mu.Lock()
defer w.mu.Unlock()
filtered := w.patterns[:0]
for _, p := range w.patterns {
if _, remove := targets[p.raw]; !remove {
filtered = append(filtered, p)
}
}
w.patterns = filtered
}
// Match reports whether path matches any registered pattern. Equivalent to calling
// MatchPathPattern for every pattern, except the path is normalised and split once.
func (w *PathWhitelist) Match(path string) bool {