Moonshark/core/runner/Context.go
2025-04-07 21:59:11 -05:00

129 lines
2.6 KiB
Go

package runner
import (
"sync"
"maps"
"github.com/valyala/bytebufferpool"
"github.com/valyala/fasthttp"
)
// Context represents execution context for a Lua script
type Context struct {
// Values stores any context values (route params, HTTP request info, etc.)
Values map[string]any
// internal mutex for concurrent access
mu sync.RWMutex
// FastHTTP context if this was created from an HTTP request
RequestCtx *fasthttp.RequestCtx
// Buffer for efficient string operations
buffer *bytebufferpool.ByteBuffer
}
// Context pool to reduce allocations
var contextPool = sync.Pool{
New: func() any {
return &Context{
Values: make(map[string]any, 16), // Pre-allocate with reasonable capacity
}
},
}
// NewContext creates a new context, potentially reusing one from the pool
func NewContext() *Context {
return contextPool.Get().(*Context)
}
// NewHTTPContext creates a new context from a fasthttp RequestCtx
func NewHTTPContext(requestCtx *fasthttp.RequestCtx) *Context {
ctx := NewContext()
ctx.RequestCtx = requestCtx
return ctx
}
// Release returns the context to the pool after clearing its values
func (c *Context) Release() {
c.mu.Lock()
defer c.mu.Unlock()
// Clear all values to prevent data leakage
for k := range c.Values {
delete(c.Values, k)
}
// Reset request context
c.RequestCtx = nil
// Return buffer to pool if we have one
if c.buffer != nil {
bytebufferpool.Put(c.buffer)
c.buffer = nil
}
contextPool.Put(c)
}
// GetBuffer returns a byte buffer for efficient string operations
func (c *Context) GetBuffer() *bytebufferpool.ByteBuffer {
c.mu.Lock()
defer c.mu.Unlock()
if c.buffer == nil {
c.buffer = bytebufferpool.Get()
}
return c.buffer
}
// Set adds a value to the context
func (c *Context) Set(key string, value any) {
c.mu.Lock()
defer c.mu.Unlock()
c.Values[key] = value
}
// Get retrieves a value from the context
func (c *Context) Get(key string) any {
c.mu.RLock()
defer c.mu.RUnlock()
return c.Values[key]
}
// Contains checks if a key exists in the context
func (c *Context) Contains(key string) bool {
c.mu.RLock()
defer c.mu.RUnlock()
_, exists := c.Values[key]
return exists
}
// Delete removes a value from the context
func (c *Context) Delete(key string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.Values, key)
}
// All returns a copy of all values in the context
func (c *Context) All() map[string]any {
c.mu.RLock()
defer c.mu.RUnlock()
result := make(map[string]any, len(c.Values))
maps.Copy(result, c.Values)
return result
}
// IsHTTPRequest returns true if this context contains a fasthttp RequestCtx
func (c *Context) IsHTTPRequest() bool {
return c.RequestCtx != nil
}