--- name: rate_limiter_check kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func RateLimiterCheck(rl *RateLimiter, key string) RateLimitResult" description: "Evalua un request del cliente identificado por key contra el token bucket. Recarga tokens segun el tiempo transcurrido y consume uno si esta permitido. Seguro para uso concurrente (mutex interno)." tags: [rate_limit, http, middleware, token_bucket, check, infra] uses_functions: [] uses_types: [RateLimiter_go_infra, RateLimitResult_go_infra] returns: [RateLimitResult_go_infra] returns_optional: false error_type: "error_go_core" imports: [math, time] params: - name: rl desc: "puntero al RateLimiter creado con RateLimiterNew" - name: key desc: "identificador del cliente (IP, API key, user ID, etc.)" output: "RateLimitResult con Allowed, Remaining, ResetAt y RetryAfter calculados a partir del estado del bucket" tested: true tests: ["primer request siempre allowed con burst-1 remaining", "consumir todos los tokens bloquea siguiente request", "los tokens se recargan con el paso del tiempo", "retryAfter es positivo cuando se rechaza", "keys distintas tienen buckets independientes"] test_file_path: "functions/infra/rate_limiter_check_test.go" file_path: "functions/infra/rate_limiter_check.go" --- ## Ejemplo ```go rl := RateLimiterNew(10, 20) result := RateLimiterCheck(rl, "192.168.1.1") if !result.Allowed { // sleep(result.RetryAfter * time.Second) o 429 } ``` ## Notas Funcion impura porque depende de tiempo wall-clock (`time.Now`) y muta el estado del limiter. Algoritmo token bucket clasico: cada bucket se recarga linealmente a `rate` tokens/segundo hasta `burst`. Un request consume 1 token. La primera vez que aparece una key se crea el bucket lleno (descontando ya el primer token). El mutex asegura uso seguro desde multiples goroutines.