Closed OrJDev closed 7 months ago
For those looking for a solution to this, I used rate-limiter-flexible
to implement a generic Redis adapter:
import { defineTRPCLimiter } from '@trpc-limiter/core'
import {
RateLimiterMemory,
RateLimiterRedis,
RateLimiterRes,
} from 'rate-limiter-flexible'
import { redis } from '../redis'
// Default 5 queries per second fallback
const rateLimiterMemory = new RateLimiterMemory({
points: 5,
duration: 1,
})
export const createTrpcRateLimiter = defineTRPCLimiter({
store: (opts) =>
new RateLimiterRedis({
storeClient: redis,
keyPrefix: 'RATE_LIMIT',
points: opts.max,
duration: opts.windowMs / 1000, // in seconds
insuranceLimiter: rateLimiterMemory,
}),
async isBlocked(store, fingerprint) {
try {
await store.consume(fingerprint)
return null
} catch (error) {
if (error instanceof RateLimiterRes) {
return Math.round(error.msBeforeNext / 1000) || 1
}
// Should not happen with `insuranceLimiter`
throw error
}
},
})
For those looking for a solution to this, I used
rate-limiter-flexible
to implement a generic Redis adapter:import { defineTRPCLimiter } from '@trpc-limiter/core' import { RateLimiterMemory, RateLimiterRedis, RateLimiterRes, } from 'rate-limiter-flexible' import { redis } from '../redis' // Default 5 queries per second fallback const rateLimiterMemory = new RateLimiterMemory({ points: 5, duration: 1, }) export const createTrpcRateLimiter = defineTRPCLimiter({ store: (opts) => new RateLimiterRedis({ storeClient: redis, keyPrefix: 'RATE_LIMIT', points: opts.max, duration: opts.windowMs / 1000, // in seconds insuranceLimiter: rateLimiterMemory, }), async isBlocked(store, fingerprint) { try { await store.consume(fingerprint) return null } catch (error) { if (error instanceof RateLimiterRes) { return Math.round(error.msBeforeNext / 1000) || 1 } // Should not happen with `insuranceLimiter` throw error } }, })
thank you for this, i used it to implement https://github.com/OrJDev/trpc-limiter/tree/main/packages/redis
Redis adapter for trpc-limiter.
For now we have an Upstash adapter but it seems like just a vanilla Redis one would be more popular.
I will be working on this on my free time, but feel free to make a pr if I haven't yet.