2023-11-02 02:11:22 +01:00
|
|
|
package iris
|
|
|
|
|
2023-11-02 14:24:45 +01:00
|
|
|
import (
|
|
|
|
"github.com/kataras/iris/v12/context"
|
|
|
|
)
|
|
|
|
|
2023-11-02 02:11:22 +01:00
|
|
|
// ContextPool is a pool of T.
|
|
|
|
//
|
|
|
|
// See `NewContextWrapper` and `ContextPool` for more.
|
|
|
|
type ContextPool[T any] interface {
|
|
|
|
Acquire(ctx Context) T
|
|
|
|
Release(T)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultContextPool is a pool of T.
|
|
|
|
// It's used to acquire and release T.
|
|
|
|
// The T is acquired from the pool and released back to the pool after the handler's execution.
|
|
|
|
// The T is passed to the handler as an argument.
|
|
|
|
// The T is not shared between requests.
|
|
|
|
type DefaultContextPool[T any] struct {
|
|
|
|
AcquireFunc func(Context) T
|
|
|
|
ReleaseFunc func(T)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that DefaultContextPool[T] implements ContextPool[T].
|
|
|
|
var _ ContextPool[any] = (*DefaultContextPool[any])(nil)
|
|
|
|
|
|
|
|
// Acquire returns a new T from the pool's AcquireFunc.
|
|
|
|
func (p *DefaultContextPool[T]) Acquire(ctx Context) T {
|
|
|
|
acquire := p.AcquireFunc
|
|
|
|
if p.AcquireFunc == nil {
|
|
|
|
acquire = func(ctx Context) T {
|
|
|
|
var t T
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return acquire(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Release does nothing if the pool's ReleaseFunc is nil.
|
|
|
|
func (p *DefaultContextPool[T]) Release(t T) {
|
|
|
|
release := p.ReleaseFunc
|
|
|
|
if p.ReleaseFunc == nil {
|
|
|
|
release = func(t T) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
release(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContextWrapper is a wrapper for handlers which expect a T instead of iris.Context.
|
|
|
|
//
|
|
|
|
// See the `NewContextWrapper` function for more.
|
|
|
|
type ContextWrapper[T any] struct {
|
|
|
|
pool ContextPool[T]
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewContextWrapper returns a new ContextWrapper.
|
|
|
|
// If pool is nil, a default pool is used.
|
|
|
|
// The default pool's AcquireFunc returns a zero value of T.
|
|
|
|
// The default pool's ReleaseFunc does nothing.
|
|
|
|
// The default pool is used when the pool is nil.
|
|
|
|
// Use the `&iris.DefaultContextPool{...}` to pass a simple context pool.
|
|
|
|
//
|
|
|
|
// See the `Handler` method for more.
|
|
|
|
// Example: https://github.com/kataras/iris/tree/main/_examples/routing/custom-context
|
|
|
|
func NewContextWrapper[T any](pool ContextPool[T]) *ContextWrapper[T] {
|
|
|
|
if pool == nil {
|
|
|
|
pool = &DefaultContextPool[T]{
|
|
|
|
AcquireFunc: func(ctx Context) T {
|
|
|
|
var t T
|
|
|
|
return t
|
|
|
|
},
|
|
|
|
ReleaseFunc: func(t T) {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ContextWrapper[T]{
|
|
|
|
pool: pool,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-02 14:24:45 +01:00
|
|
|
// Pool returns the pool, useful when manually Acquire and Release of custom context is required.
|
|
|
|
func (w *ContextWrapper[T]) Pool() ContextPool[T] {
|
|
|
|
return w.pool
|
|
|
|
}
|
|
|
|
|
2023-11-02 02:11:22 +01:00
|
|
|
// Handler wraps the handler with the pool's Acquire and Release methods.
|
|
|
|
// It returns a new handler which expects a T instead of iris.Context.
|
|
|
|
// The T is the type of the pool.
|
|
|
|
// The T is acquired from the pool and released back to the pool after the handler's execution.
|
|
|
|
// The T is passed to the handler as an argument.
|
|
|
|
// The T is not shared between requests.
|
|
|
|
func (w *ContextWrapper[T]) Handler(handler func(T)) Handler {
|
2023-11-02 14:24:45 +01:00
|
|
|
if handler == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-02 02:11:22 +01:00
|
|
|
return func(ctx Context) {
|
|
|
|
newT := w.pool.Acquire(ctx)
|
|
|
|
handler(newT)
|
|
|
|
w.pool.Release(newT)
|
|
|
|
}
|
|
|
|
}
|
2023-11-02 14:24:45 +01:00
|
|
|
|
|
|
|
// Handlers wraps the handlers with the pool's Acquire and Release methods.
|
|
|
|
func (w *ContextWrapper[T]) Handlers(handlers ...func(T)) context.Handlers {
|
|
|
|
newHandlers := make(context.Handlers, len(handlers))
|
|
|
|
for i, handler := range handlers {
|
|
|
|
newHandlers[i] = w.Handler(handler)
|
|
|
|
}
|
|
|
|
|
|
|
|
return newHandlers
|
|
|
|
}
|