Documentation
¶
Index ¶
- func GetResourceProtectionType(err error) string
- func IsResourceProtectionError(err error) bool
- type BatchLimiter
- type MemoryAlert
- type MemoryMonitor
- type ProtectionError
- type ResourceLimits
- type ResourceProtector
- func (rp *ResourceProtector) GetBatchLimiter() *BatchLimiter
- func (rp *ResourceProtector) GetStats() ResourceStats
- func (rp *ResourceProtector) HealthCheck() map[string]any
- func (rp *ResourceProtector) SampleMemory()
- func (rp *ResourceProtector) SecureBodyReader(r *http.Request) ([]byte, error)
- func (rp *ResourceProtector) SetMemoryAlertCallback(alertCallback func(MemoryAlert))
- type ResourceStats
- type SimpleLimiter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetResourceProtectionType ¶
GetResourceProtectionType returns the type of resource protection error
func IsResourceProtectionError ¶
IsResourceProtectionError checks if an error is a resource protection error
Types ¶
type BatchLimiter ¶
type BatchLimiter struct {
// contains filtered or unexported fields
}
BatchLimiter provides batch operation protection
func (*BatchLimiter) AcquireBatch ¶
func (bl *BatchLimiter) AcquireBatch(ctx context.Context, batchSize int) error
AcquireBatch acquires permission for a batch operation
func (*BatchLimiter) ReleaseBatch ¶
func (bl *BatchLimiter) ReleaseBatch()
ReleaseBatch releases batch operation permission
type MemoryAlert ¶
type MemoryAlert struct {
Timestamp time.Time `json:"timestamp"`
Type string `json:"type"`
Severity string `json:"severity"`
CurrentMB int64 `json:"current_mb"`
LimitMB int64 `json:"limit_mb"`
UsagePercent float64 `json:"usage_percent"`
}
MemoryAlert represents a memory usage alert
type MemoryMonitor ¶
type MemoryMonitor struct {
// contains filtered or unexported fields
}
MemoryMonitor samples memory usage on demand.
It owns no goroutine and no timer: a caller invokes Sample (directly or through ResourceProtector.SampleMemory) inside the work it wants measured — normally a request or handler invocation. On-demand sampling is the only shape that fits a Lambda execution environment, which is frozen the moment a handler returns; a background sampling loop would either be frozen mid-flight or, if started during module initialization, resume against an invocation that is already over.
func (*MemoryMonitor) Sample ¶
func (mm *MemoryMonitor) Sample()
Sample records current memory usage on demand: it reads the runtime's memory statistics, updates the peak, and, when usage is at or above the configured panic threshold, records an alert, invokes the alert callback, and forces a garbage collection. It is the whole of this type's behavior: no goroutine and no timer are involved.
type ProtectionError ¶
ProtectionError represents a resource protection error
func (*ProtectionError) Error ¶
func (e *ProtectionError) Error() string
type ResourceLimits ¶
type ResourceLimits struct {
// HTTP request limits
MaxRequestBodySize int64 `json:"max_request_body_size" yaml:"max_request_body_size"`
MaxRequestTimeout time.Duration `json:"max_request_timeout" yaml:"max_request_timeout"`
MaxConcurrentReq int `json:"max_concurrent_requests" yaml:"max_concurrent_requests"`
// Batch operation limits
MaxBatchSize int `json:"max_batch_size" yaml:"max_batch_size"`
MaxConcurrentBatch int `json:"max_concurrent_batch" yaml:"max_concurrent_batch"`
BatchRateLimit float64 `json:"batch_rate_limit" yaml:"batch_rate_limit"`
// Memory limits. Memory is sampled on demand (see
// ResourceProtector.SampleMemory), so there is no check interval.
MaxMemoryMB int64 `json:"max_memory_mb" yaml:"max_memory_mb"`
MemoryPanicThreshold float64 `json:"memory_panic_threshold" yaml:"memory_panic_threshold"`
// Rate limiting
RequestsPerSecond float64 `json:"requests_per_second" yaml:"requests_per_second"`
BurstSize int `json:"burst_size" yaml:"burst_size"`
}
ResourceLimits defines configurable resource limits
func DefaultResourceLimits ¶
func DefaultResourceLimits() ResourceLimits
DefaultResourceLimits returns secure default limits
type ResourceProtector ¶
type ResourceProtector struct {
// contains filtered or unexported fields
}
ResourceProtector provides resource protection and monitoring
func NewResourceProtector ¶
func NewResourceProtector(config ResourceLimits) *ResourceProtector
NewResourceProtector creates a new resource protector
func (*ResourceProtector) GetBatchLimiter ¶
func (rp *ResourceProtector) GetBatchLimiter() *BatchLimiter
GetBatchLimiter returns a batch limiter
func (*ResourceProtector) GetStats ¶
func (rp *ResourceProtector) GetStats() ResourceStats
GetStats returns current resource usage statistics
func (*ResourceProtector) HealthCheck ¶
func (rp *ResourceProtector) HealthCheck() map[string]any
HealthCheck performs a resource protection health check
func (*ResourceProtector) SampleMemory ¶
func (rp *ResourceProtector) SampleMemory()
SampleMemory samples current memory usage on demand, updating the protector's memory statistics and invoking the alert callback when the configured threshold is crossed. It is synchronous: it returns only after the sample has been recorded, and it starts nothing that could run after the caller returns. Call it inside a request to have the request's memory use recorded; there is no background sampler.
func (*ResourceProtector) SecureBodyReader ¶
func (rp *ResourceProtector) SecureBodyReader(r *http.Request) ([]byte, error)
SecureBodyReader reads an HTTP request body under a byte-size limit, a per-request wall-clock timeout, and the protector's shared concurrency and rate limits.
It holds one request-concurrency slot while it reads the body, and releases that slot no later than MaxRequestTimeout. On timeout the slot is released before the body cleanup runs, so a client that declares a body and withholds it cannot keep a slot past the timeout: the timeout path still closes the body and joins its reader, but neither of those blocking operations may extend the slot's lifetime. With the previous in-order release they did keep the slot until the client disconnected, and MaxConcurrentReq stalled connections rejected every other request.
The trade-off is explicit. Go's HTTP/1 request body can block both Read and Close on the same stalled socket, so on timeout this call — and the handler goroutine running it — can stay blocked until the client disconnects or a transport deadline fires; the reader goroutine is joined rather than abandoned, so nothing outlives the call, but the call itself does not return at the timeout. Lambda freezes the execution environment when the handler returns; here the handler does not return, so the stalled invocation is held until it times out while the shared concurrency slot is already free. An application that serves live HTTP/1 requests through this helper should impose a server- or upstream-level body-read deadline (for example net/http's Server.ReadTimeout) so the read ends before this last-resort path is reached.
func (*ResourceProtector) SetMemoryAlertCallback ¶
func (rp *ResourceProtector) SetMemoryAlertCallback(alertCallback func(MemoryAlert))
SetMemoryAlertCallback sets the callback invoked when a sample crosses the configured memory threshold. The callback runs on whichever goroutine called Sample; it is called synchronously, inside the work that requested the sample, so it never outlives the invocation that triggered it.
type ResourceStats ¶
type ResourceStats struct {
LastStatsUpdate time.Time `json:"last_stats_update"`
ConcurrentBatchOps int64 `json:"concurrent_batch_operations"`
ConcurrentRequests int64 `json:"concurrent_requests"`
MaxConcurrentReq int64 `json:"max_concurrent_requests"`
TotalBatchOps int64 `json:"total_batch_operations"`
RejectedBatchOps int64 `json:"rejected_batch_operations"`
TotalRequests int64 `json:"total_requests"`
MaxConcurrentBatch int64 `json:"max_concurrent_batch"`
CurrentMemoryMB int64 `json:"current_memory_mb"`
PeakMemoryMB int64 `json:"peak_memory_mb"`
MemoryAlerts int64 `json:"memory_alerts"`
RateLimitHits int64 `json:"rate_limit_hits"`
RejectedRequests int64 `json:"rejected_requests"`
}
ResourceStats tracks resource usage statistics
type SimpleLimiter ¶
type SimpleLimiter struct {
// contains filtered or unexported fields
}
SimpleLimiter is a basic rate limiter implementation
func NewSimpleLimiter ¶
func NewSimpleLimiter(rps float64, burst int) *SimpleLimiter
NewSimpleLimiter creates a new simple rate limiter
func (*SimpleLimiter) Allow ¶
func (l *SimpleLimiter) Allow() bool
Allow checks if a request is allowed