Skip to content

Commit fed79e7

Browse files
committed
Merge branch 'main' into v3/worker-attempt-creation
2 parents b6e105a + 782d4f7 commit fed79e7

File tree

8 files changed

+283
-48
lines changed

8 files changed

+283
-48
lines changed

apps/proxy/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
"dev": "wrangler dev"
88
},
99
"devDependencies": {
10-
"@cloudflare/workers-types": "^4.20230419.0",
10+
"@cloudflare/workers-types": "^4.20240512.0",
1111
"typescript": "^5.0.4",
12-
"wrangler": "^3.0.0"
12+
"wrangler": "^3.57.1"
1313
},
1414
"dependencies": {
1515
"@aws-sdk/client-sqs": "^3.445.0",

apps/proxy/src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { queueEvent } from "./events/queueEvent";
22
import { queueEvents } from "./events/queueEvents";
3+
import { applyRateLimit } from "./rateLimit";
4+
import { Ratelimit } from "./rateLimiter";
35

46
export interface Env {
57
/** The hostname needs to be changed to allow requests to pass to the Trigger.dev platform */
@@ -9,6 +11,8 @@ export interface Env {
911
AWS_SQS_SECRET_ACCESS_KEY: string;
1012
AWS_SQS_QUEUE_URL: string;
1113
AWS_SQS_REGION: string;
14+
//rate limiter
15+
API_RATE_LIMITER: Ratelimit;
1216
}
1317

1418
export default {
@@ -25,13 +29,13 @@ export default {
2529
switch (url.pathname) {
2630
case "/api/v1/events": {
2731
if (request.method === "POST") {
28-
return queueEvent(request, env);
32+
return applyRateLimit(request, env, () => queueEvent(request, env));
2933
}
3034
break;
3135
}
3236
case "/api/v1/events/bulk": {
3337
if (request.method === "POST") {
34-
return queueEvents(request, env);
38+
return applyRateLimit(request, env, () => queueEvents(request, env));
3539
}
3640
break;
3741
}

apps/proxy/src/rateLimit.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Env } from "src";
2+
import { getApiKeyFromRequest } from "./apikey";
3+
import { json } from "./json";
4+
5+
export async function applyRateLimit(
6+
request: Request,
7+
env: Env,
8+
fn: () => Promise<Response>
9+
): Promise<Response> {
10+
const apiKey = getApiKeyFromRequest(request);
11+
if (apiKey) {
12+
const result = await env.API_RATE_LIMITER.limit({ key: `apikey-${apiKey.apiKey}` });
13+
const { success } = result;
14+
console.log(`Rate limiter`, {
15+
success,
16+
key: `${apiKey.apiKey.substring(0, 12)}...`,
17+
});
18+
if (!success) {
19+
//60s in the future
20+
const reset = Date.now() + 60 * 1000;
21+
const secondsUntilReset = Math.max(0, (reset - new Date().getTime()) / 1000);
22+
23+
return json(
24+
{
25+
title: "Rate Limit Exceeded",
26+
status: 429,
27+
type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429",
28+
detail: `Rate limit exceeded. Retry in ${secondsUntilReset} seconds.`,
29+
error: `Rate limit exceeded. Retry in ${secondsUntilReset} seconds.`,
30+
reset,
31+
},
32+
{
33+
status: 429,
34+
headers: {
35+
"x-ratelimit-reset": reset.toString(),
36+
},
37+
}
38+
);
39+
}
40+
} else {
41+
console.log(`Rate limiter: no API key for request`);
42+
}
43+
44+
//call the original function
45+
return fn();
46+
}

apps/proxy/src/rateLimiter.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export interface Ratelimit {
2+
/*
3+
* The ratelimit function
4+
* @param {RatelimitOptions} options
5+
* @returns {Promise<RatelimitResponse>}
6+
*/
7+
limit: (options: RatelimitOptions) => Promise<RatelimitResponse>;
8+
}
9+
10+
export interface RatelimitOptions {
11+
/*
12+
* The key to identify the user, can be an IP address, user ID, etc.
13+
*/
14+
key: string;
15+
}
16+
17+
export interface RatelimitResponse {
18+
/*
19+
* The ratelimit success status
20+
* @returns {boolean}
21+
*/
22+
success: boolean;
23+
}

apps/proxy/wrangler.toml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,33 @@
11
name = "proxy"
22
main = "src/index.ts"
3-
compatibility_date = "2023-10-30"
3+
compatibility_date = "2024-05-13"
44
compatibility_flags = [ "nodejs_compat" ]
55

66
[env.staging]
7-
[env.prod]
7+
# The rate limiting API is in open beta.
8+
[[env.staging.unsafe.bindings]]
9+
name = "API_RATE_LIMITER"
10+
type = "ratelimit"
11+
# An identifier you define, that is unique to your Cloudflare account.
12+
# Must be an integer.
13+
namespace_id = "1"
14+
15+
# Limit: the number of tokens allowed within a given period in a single
16+
# Cloudflare location
17+
# Period: the duration of the period, in seconds. Must be either 10 or 60
18+
simple = { limit = 100, period = 60 }
19+
20+
21+
[env.prod]
22+
# The rate limiting API is in open beta.
23+
[[env.prod.unsafe.bindings]]
24+
name = "API_RATE_LIMITER"
25+
type = "ratelimit"
26+
# An identifier you define, that is unique to your Cloudflare account.
27+
# Must be an integer.
28+
namespace_id = "2"
29+
30+
# Limit: the number of tokens allowed within a given period in a single
31+
# Cloudflare location
32+
# Period: the duration of the period, in seconds. Must be either 10 or 60
33+
simple = { limit = 300, period = 60 }

docs/v3/github-actions.mdx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,24 @@ To set it in GitHub go to your repository, click on "Settings", "Secrets and var
9595
## Version pinning
9696

9797
The CLI and `@trigger.dev/*` package versions need to be in sync, otherwise there will be errors and unpredictable behavior. Hence, the `deploy` command will automatically fail during CI on any version mismatches.
98-
99-
To ensure a smooth CI experience you can pin the CLI version in the deploy step, like so:
98+
Tip: add the deploy command to your `package.json` file to keep versions managed in the same place. For example:
99+
100+
```json
101+
{
102+
"scripts": {
103+
"deploy:trigger-prod": "npx [email protected] deploy",
104+
"deploy:trigger": "npx [email protected] deploy --env staging"
105+
}
106+
}
107+
```
108+
Your workflow file will follow the version specified in the `package.json` script, like so:
100109

101110
```yaml .github/workflows/release-trigger.yml
102111
- name: 🚀 Deploy Trigger.dev
103112
env:
104113
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
105114
run: |
106-
npx [email protected] deploy
115+
npm run deploy:trigger
107116
```
108117

109118
You should use the version you run locally during dev and manual deploy. The current version is displayed in the banner, but you can also check it by appending `--version` to any command.

docs/v3/upgrading-from-v2.mdx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,16 @@ async function yourBackendFunction() {
171171

172172
## Upgrading your project
173173

174-
Just follow the [v3 quick start](/v3/quick-start) to get started with v3. Our new CLI will take care of the rest.
174+
1. Make sure to upgrade all of your trigger.dev packages to v3 first.
175+
176+
```bash
177+
npx @trigger.dev/cli@beta update --to beta
178+
```
179+
180+
2. Follow the [v3 quick start](/v3/quick-start) to get started with v3. Our new CLI will take care of the rest.
175181

176182
## Using v2 together with v3
177183

178184
You can use v2 and v3 in the same codebase. This can be useful where you already have v2 jobs or where we don't support features you need (yet).
179185

180-
<Snippet file="incomplete-docs.mdx" />
186+
<Note>We do not support calling v3 tasks from v2 jobs or vice versa.</Note>

0 commit comments

Comments
 (0)