diff --git a/examples/nodejs-cf-worker/.gitignore b/examples/nodejs-cf-worker/.gitignore index 3b0fe33..6bffef3 100644 --- a/examples/nodejs-cf-worker/.gitignore +++ b/examples/nodejs-cf-worker/.gitignore @@ -7,7 +7,6 @@ yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* - # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json diff --git a/examples/nodejs-cf-worker/src/index.ts b/examples/nodejs-cf-worker/src/index.ts index fe14b90..a5bd8f6 100644 --- a/examples/nodejs-cf-worker/src/index.ts +++ b/examples/nodejs-cf-worker/src/index.ts @@ -24,8 +24,17 @@ * @see https://developers.cloudflare.com/workers/configuration/secrets/ */ +import { DurableObject } from 'cloudflare:workers'; import { z } from 'zod'; +// const WHITEGLOVE_MAP = { +// "api.thegraph.com/subgraphs/name/schmidsi/anudit-lens": { +// "" +// "rateLimit": 100, +// "rateLimitWindow": 6 +// } +// } + const GraphqlReqSchema = z.object({ query: z.string().min(1), operationName: z.string().optional().nullable(), @@ -41,6 +50,36 @@ export default { return new Response('Unsupported', { status: 400 }); } + // TODO: per subgraph rate limiting + const id = env.RATE_LIMITER.idFromName('global'); + + console.log('Hello Pranav'); + + try { + const stub = env.RATE_LIMITER.get(id); + // const milliseconds_to_next_request = await ; + + // console.log(milliseconds_to_next_request, 'milliseconds_to_next_request') + + if (await stub.rateLimit()) { + // Alternatively one could sleep for the necessary length of time + return new Response( + JSON.stringify({ + errors: [ + { + message: + 'Rate limit on ENS communtiy key exceeded. Try again later or got to https://thegraph.com/studio to create your own API key. Find the ENS subgraph here: https://thegraph.com/explorer/subgraphs/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH?v=1&view=Overview&chain=arbitrum-one', + }, + ], + }), + { status: 429 } + ); + } + } catch (error) { + console.log(error, 'error') + return new Response('Could not connect to rate limiter', { status: 502 }); + } + const response = await querySubgraph(req, env); if (response.status !== 200) { return new Response(response.statusText, { status: response.status }); @@ -66,8 +105,32 @@ async function querySubgraph(req: Request, env: Env) { method: 'POST', body: JSON.stringify(gqlRequest), headers: { - authorization: `Bearer ${env.API_KEY}`, + // authorization: `Bearer ${env.API_KEY}`, 'Content-Type': 'application/json', }, }); } + +export class RateLimiter extends DurableObject { + static milliseconds_per_request = 10000; + + lastRequest: number; + + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + this.lastRequest = 0; + } + + async rateLimit(): Promise { + const now = Date.now(); + + console.log(now, this.lastRequest, RateLimiter.milliseconds_per_request); + + if (now - this.lastRequest > RateLimiter.milliseconds_per_request) { + this.lastRequest = now; + return false; + } else { + return true + } + } + } \ No newline at end of file diff --git a/examples/nodejs-cf-worker/worker-configuration.d.ts b/examples/nodejs-cf-worker/worker-configuration.d.ts index 1a4360a..06854bc 100644 --- a/examples/nodejs-cf-worker/worker-configuration.d.ts +++ b/examples/nodejs-cf-worker/worker-configuration.d.ts @@ -1,7 +1,8 @@ -// Generated by Wrangler on Mon May 13 2024 08:41:07 GMT-1000 (Hawaii-Aleutian Standard Time) +// Generated by Wrangler on Fri May 17 2024 19:36:49 GMT+0200 (Central European Summer Time) // by running `wrangler types` interface Env { - SUBGRAPH_ENDPOINT: "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/DZz4kDTdmzWLWsV373w2bSmoar3umKKH9y82SUKr5qmp"; + SUBGRAPH_ENDPOINT: "https://gateway-arbitrum.network.thegraph.com/api/25eb15e49c08702d60d90be66dd9a9a3/subgraphs/id/74z4nnW6cr62ox3fLFaD3muieJzMXJimi6EZsG52yChM"; API_KEY: string; + RATE_LIMITER: DurableObjectNamespace; } diff --git a/examples/nodejs-cf-worker/wrangler.toml b/examples/nodejs-cf-worker/wrangler.toml index 330621d..bac35e4 100644 --- a/examples/nodejs-cf-worker/wrangler.toml +++ b/examples/nodejs-cf-worker/wrangler.toml @@ -1,5 +1,5 @@ #:schema node_modules/wrangler/config-schema.json -name = "nodejs-cf-worker" +name = "redirect-rate-limit-network-test" main = "src/index.ts" compatibility_date = "2024-05-12" @@ -16,4 +16,12 @@ mode = "smart" # Replace this with your subgraph endpoint [vars] -SUBGRAPH_ENDPOINT = "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/DZz4kDTdmzWLWsV373w2bSmoar3umKKH9y82SUKr5qmp" +SUBGRAPH_ENDPOINT = "https://gateway-arbitrum.network.thegraph.com/api/25eb15e49c08702d60d90be66dd9a9a3/subgraphs/id/74z4nnW6cr62ox3fLFaD3muieJzMXJimi6EZsG52yChM" + +[[durable_objects.bindings]] +name = "RATE_LIMITER" +class_name = "RateLimiter" + +[[migrations]] +tag = "v1" +new_classes = ["RateLimiter"] \ No newline at end of file