Cloudflare DevelopersCD
Cloudflare Developers4mo ago
26 replies
Marak

RateLimiter Durable Object Discussion

something like:

import { DurableObject } from 'cloudflare:workers';

let LOCK_TIMEOUT = 5000; // 5 seconds
let RATE_LIMIT_WINDOW = 200; // 200 milliseconds, now using stamina in cast system

// UserLock.js
export default class RateLimitkDurableObject extends DurableObject {
  constructor(state, env) {
    super(state, env);
    this.state = state;
    this.env = env;
  }

  async acquireLock() {

    // Check if user is locked
    const isLocked = await this.state.storage.get("isLocked");
    if (isLocked) {
      // check lastInteraction
      const lastInteraction = (await this.state.storage.get("lastInteraction")) || 0;
      if (Date.now() - lastInteraction < LOCK_TIMEOUT) {
        throw new Error("User is currently locked");
      }
    }

    // Check rate limit (e.g., 1 request per 15 seconds)
    const lastInteraction = (await this.state.storage.get("lastInteraction")) || 0;
    const now = Date.now();
    const rateLimitWindow = RATE_LIMIT_WINDOW;
    if (now - lastInteraction < rateLimitWindow) {
      let timeLeft = Math.ceil((rateLimitWindow - (now - lastInteraction)) / 1000);
      throw new Error(`Please try again in ${timeLeft} seconds.`);
    }

    // Acquire lock and update last interaction time
    await this.state.storage.put("isLocked", true);
    await this.state.storage.put("lastInteraction", now);

    return { status: "Lock acquired" };
  }

  async releaseLock() {
    // Release lock
    console.log("Releasing lock for user");
    await this.state.storage.put("isLocked", false);
    return { status: "Lock released" };
  }
}
Was this page helpful?