Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrCapacityExceeded = errors.New("ipthrottle: capacity exceeded")
ErrCapacityExceeded is returned by a Store's Increment when the store is already tracking cfg.MaxIPs distinct keys and the incoming key is new.
Functions ¶
func Increment ¶
func Increment(store kv.Store, key string, window time.Duration, maxKeys int, now time.Time) (int, error)
Increment records one request for key within window (relative to now) against store, resetting the count if the previous window has elapsed, and returns the count so far in the current window. Per-key state (count, window start) is JSON-encoded and mutated race-free via kv.Store.Mutate, which reproduces the exact "reset on elapsed window, otherwise increment" semantics this package has always had, on top of any kv.Store implementation (kv.MemoryStore, kv.FileStore, or otherwise).
If store is not yet tracking key and is already at maxKeys distinct keys (maxKeys <= 0 means unlimited), Increment returns ErrCapacityExceeded without recording the request.
The maxKeys cardinality guard is checked via a Get+Len pair before the Mutate call, since only Mutate holds the per-key lock and kv.Store has no facility for locking a key that does not exist yet while a separate, store-wide Len() check runs. This means the check is a soft/approximate cap under heavy concurrent creation of brand-new distinct keys: two concurrent Increment calls for two different new keys can both observe Len() < maxKeys and both be admitted, so the cardinality bound can be exceeded by a small margin under contention. The pre-retrofit implementation held a single mutex across the entire check-then-insert sequence and so enforced an exact bound; kv.Store's per-key Mutate lock does not extend to a store-wide cardinality decision, so this is a deliberate, documented trade-off rather than an oversight.
func New ¶
func New(cfg Config) fh.HandlerFunc
Types ¶
type Config ¶
type Config struct {
MaxPerIP int
GlobalMax int
MaxIPs int
Window time.Duration
KeyFunc func(fh.Ctx) string
Reject RejectHandler
// Store holds per-IP window/count state, keyed by IP and JSON-encoded
// via Increment. Defaults to a new kv.MemoryStore, which reproduces the
// exact map+mutex+sweep behavior this package has always used. Pass a
// kv.FileStore (see github.com/oarkflow/fh/pkg/storage/kv) to persist
// counters across restarts.
Store kv.Store
}