Posted to tcl by apn at Sat Feb 01 16:43:23 GMT 2025view pretty

# Code generated by ChatGPT
package require Tcl 8.6
package require tcltest

namespace eval RateLimiter {
    variable limits
    array set limits {}

    proc allow_request {key max_requests time_window} {
        variable limits
        set now [clock milliseconds]
        
        if {![info exists limits($key)]} {
            set limits($key) "$max_requests $now"
        }
        
        lassign $limits($key) tokens last_time
        
        set elapsed [expr {$now - $last_time}]
        set new_tokens [expr {int($elapsed / $time_window) * $max_requests}]
        
        set tokens [expr {min($tokens + $new_tokens, $max_requests)}]
        set last_time [expr {$now - ($elapsed % $time_window)}]
        
        if {$tokens > 0} {
            set tokens [expr {$tokens - 1}]
            set limits($key) "$tokens $last_time"
            return 1
        } else {
            return 0
        }
    }
}

# Example usage:
# puts [RateLimiter::allow_request "user_1" 5 1000]

# Test cases
namespace eval RateLimiterTest {
    namespace import ::tcltest::*
    
    test allow_request_1 "Test first request is allowed" {
        RateLimiter::allow_request "test_user" 3 1000
    } -result 1
    
    test allow_request_2 "Test multiple requests within limit" {
        set res [list]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        join $res ","
    } -result "1,1,1"
    
    test allow_request_3 "Test request exceeding limit is denied" {
        set res [list]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        join $res ","
    } -result "1,1,1,0"
    
    test allow_request_4 "Test rolling window allows new requests over time" {
        set res [list]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        after 1100
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        join $res ","
    } -result "1,1,1,1"
    
    test allow_request_5 "Test requests spread over multiple windows" {
        set res [list]
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        after 500
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        after 500
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        after 1100
        lappend res [RateLimiter::allow_request "test_user" 3 1000]
        join $res ","
    } -result "1,1,1,1"
}