upstash / ratelimit-js

Rate limiting library for serverless runtimes
https://ratelimit-with-upstash.vercel.app/
MIT License
1.72k stars 33 forks source link

Ratelimit doesn't seem to return proper reset time #59

Closed Gnoll94 closed 10 months ago

Gnoll94 commented 1 year ago

I'm trying to get an accurate TTL for a rate limit I have set up using Upstash

import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});

My rate limit is set up like

const ratelimit = new Ratelimit({
  redis: redis,
  limiter: Ratelimit.fixedWindow(1, "4h"),
});

I then have the following headers being set

    const identifier = `receive:${ip}`;
    const result = await ratelimit.limit(identifier);
    res.setHeader("X-RateLimit-Limit", result.limit);
    res.setHeader("X-RateLimit-Remaining", result.remaining);
    res.setHeader("X-RateLimit-Reset", result.reset);

When I make the request & get back the result.reset it doesn't seem to match what I'd expect. Am I looking at the wrong field to get the key TTL?

In this case, I have my Data Browser fully cleared beforehand & cache flushed. When I make the request and go into the Upstash viewer, I can find the key & the expiration it has is correct (A single request, 4 hour limit, 14400s)

image

However, the result.reset value I'm getting back from this same call await ratelimit.limit(identifier); doesn't match up to the Upstash TTL

image

It never seems to give me back anything that's useable to identify when the limit expires, sometimes seemingly giving me the same UNIX timestamp even after clearing the DB. Not sure if there's something I'm missing about my implementation?

chronark commented 1 year ago

Hey, the expiry on the key is actually not used to do ratelimiting in this case. We could do it like that but right now it's not instead we're creating a new key per window and just adding expiry to eventually clean up everything.

you can very easily calculate the end of the window from the key itself:

const windowDuration = 10000 // milliseconds
const bucket = Math.floor(Date.now() / windowDuration);
const reset = (bucket + 1) * windowDuration;
github-actions[bot] commented 11 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

github-actions[bot] commented 10 months ago

This issue was closed because it has been stalled for 30 days with no activity.

Gnoll94 commented 7 months ago

I got sidetracked from this for a while, but I'm not sure this addresses the issue I was having. I essentially just need to do

const result = await ratelimit.limit(identifier);

If the identifier is already rateLimited, I'd like to get the TTL of it (How much longer is left on the rate limit?) Based off the data being returned from this. Is that a possible value to figure out?