@thirdweb-dev/service-utils 0.9.1 → 0.9.2-nightly-4c1f384a635054a8cfaaa487e3ba7ada63b221ec-20250415110008

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rateLimit = rateLimit;
4
- const RATE_LIMIT_WINDOW_SECONDS = 10;
4
+ const SLIDING_WINDOW_SECONDS = 10;
5
+ /**
6
+ * Increments the request count for this team and returns whether the team has hit their rate limit.
7
+ * Uses a sliding 10 second window.
8
+ * @param args
9
+ * @returns
10
+ */
5
11
  async function rateLimit(args) {
6
- const { team, limitPerSecond, serviceConfig, redis, sampleRate = 1.0, increment = 1, } = args;
7
- const shouldSampleRequest = Math.random() < sampleRate;
8
- if (!shouldSampleRequest) {
9
- return {
10
- rateLimited: false,
11
- requestCount: 0,
12
- rateLimit: 0,
13
- };
14
- }
12
+ const { team, limitPerSecond, serviceConfig, redis, increment = 1 } = args;
13
+ const { serviceScope } = serviceConfig;
15
14
  if (limitPerSecond === 0) {
16
15
  // No rate limit is provided. Assume the request is not rate limited.
17
16
  return {
@@ -20,40 +19,43 @@ async function rateLimit(args) {
20
19
  rateLimit: 0,
21
20
  };
22
21
  }
23
- const serviceScope = serviceConfig.serviceScope;
24
- // Gets the 10-second window for the current timestamp.
25
- const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) *
26
- RATE_LIMIT_WINDOW_SECONDS;
27
- const key = `rate-limit:${serviceScope}:${team.id}:${timestampWindow}`;
28
- // first read the request count from redis
29
- const requestCount = Number((await redis.get(key).catch(() => "0")) || "0");
30
- // Get the limit for this window accounting for the sample rate.
31
- const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
32
- if (requestCount > limitPerWindow) {
22
+ // Enforce rate limit: sum the total requests in the last `SLIDING_WINDOW_SECONDS` seconds.
23
+ const currentSecond = Math.floor(Date.now() / 1000);
24
+ const keys = Array.from({ length: SLIDING_WINDOW_SECONDS }, (_, i) => getRequestCountAtSecondCacheKey(serviceScope, team.id, currentSecond - i));
25
+ const counts = await redis.mget(keys);
26
+ const totalCount = counts.reduce((sum, count) => sum + (count ? Number.parseInt(count) : 0), 0);
27
+ const limitPerWindow = limitPerSecond * SLIDING_WINDOW_SECONDS;
28
+ if (totalCount > limitPerWindow) {
33
29
  return {
34
30
  rateLimited: true,
35
- requestCount,
31
+ requestCount: totalCount,
36
32
  rateLimit: limitPerWindow,
37
33
  status: 429,
38
- errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
34
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. Please upgrade your plan to get higher rate limits.`,
39
35
  errorCode: "RATE_LIMIT_EXCEEDED",
40
36
  };
41
37
  }
42
- // do not await this, it just needs to execute at all
43
- (async () =>
44
- // always incrementBy the amount specified for the key
45
- await redis.incrby(key, increment).then(async () => {
46
- // if the initial request count was 0, set the key to expire in the future
47
- if (requestCount === 0) {
48
- await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
38
+ // Non-blocking: increment the request count for the current second.
39
+ (async () => {
40
+ try {
41
+ const key = getRequestCountAtSecondCacheKey(serviceScope, team.id, currentSecond);
42
+ await redis.incrby(key, increment);
43
+ // If this is the first time setting this key, expire it after the sliding window is past.
44
+ if (counts[0] === null) {
45
+ await redis.expire(key, SLIDING_WINDOW_SECONDS + 1);
46
+ }
49
47
  }
50
- }))().catch(() => {
51
- console.error("Error incrementing rate limit key", key);
52
- });
48
+ catch (error) {
49
+ console.error("Error updating rate limit key:", error);
50
+ }
51
+ })();
53
52
  return {
54
53
  rateLimited: false,
55
- requestCount: requestCount + increment,
54
+ requestCount: totalCount + increment,
56
55
  rateLimit: limitPerWindow,
57
56
  };
58
57
  }
58
+ function getRequestCountAtSecondCacheKey(serviceScope, teamId, second) {
59
+ return `rate-limit:${serviceScope}:${teamId}:${second}`;
60
+ }
59
61
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":";;AAYA,8BAuFC;AAhGD,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAS9B,KAAK,UAAU,SAAS,CAAC,IAgB/B;IACC,MAAM,EACJ,IAAI,EACJ,cAAc,EACd,aAAa,EACb,KAAK,EACL,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,CAAC,GACd,GAAG,IAAI,CAAC;IAET,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC;IACvD,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,qEAAqE;QACrE,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IAEhD,uDAAuD;IACvD,MAAM,eAAe,GACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,yBAAyB,CAAC,CAAC;QAC3D,yBAAyB,CAAC;IAC5B,MAAM,GAAG,GAAG,cAAc,YAAY,IAAI,IAAI,CAAC,EAAE,IAAI,eAAe,EAAE,CAAC;IAEvE,0CAA0C;IAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAE5E,gEAAgE;IAChE,MAAM,cAAc,GAClB,cAAc,GAAG,UAAU,GAAG,yBAAyB,CAAC;IAE1D,IAAI,YAAY,GAAG,cAAc,EAAE,CAAC;QAClC,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,YAAY;YACZ,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,GAAG;YACX,YAAY,EAAE,wBAAwB,YAAY,kBAAkB,cAAc,sFAAsF;YACxK,SAAS,EAAE,qBAAqB;SACjC,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,CAAC,KAAK,IAAI,EAAE;IACV,uDAAuD;IACvD,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;QACjD,0EAA0E;QAC1E,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,YAAY,GAAG,SAAS;QACtC,SAAS,EAAE,cAAc;KAC1B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":";;AAkBA,8BAsEC;AArFD,MAAM,sBAAsB,GAAG,EAAE,CAAC;AASlC;;;;;GAKG;AACI,KAAK,UAAU,SAAS,CAAC,IAU/B;IACC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IAC3E,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC;IAEvC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,qEAAqE;QACrE,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnE,+BAA+B,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,aAAa,GAAG,CAAC,CAAC,CAC1E,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1D,CAAC,CACF,CAAC;IAEF,MAAM,cAAc,GAAG,cAAc,GAAG,sBAAsB,CAAC;IAE/D,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAChC,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,UAAU;YACxB,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,GAAG;YACX,YAAY,EAAE,wBAAwB,YAAY,kBAAkB,cAAc,gEAAgE;YAClJ,SAAS,EAAE,qBAAqB;SACjC,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,CAAC,KAAK,IAAI,EAAE;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,+BAA+B,CACzC,YAAY,EACZ,IAAI,CAAC,EAAE,EACP,aAAa,CACd,CAAC;YACF,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACnC,0FAA0F;YAC1F,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,UAAU,GAAG,SAAS;QACpC,SAAS,EAAE,cAAc;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CACtC,YAA+C,EAC/C,MAAc,EACd,MAAc;IAEd,OAAO,cAAc,YAAY,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;AAC1D,CAAC"}
@@ -1,14 +1,13 @@
1
- const RATE_LIMIT_WINDOW_SECONDS = 10;
1
+ const SLIDING_WINDOW_SECONDS = 10;
2
+ /**
3
+ * Increments the request count for this team and returns whether the team has hit their rate limit.
4
+ * Uses a sliding 10 second window.
5
+ * @param args
6
+ * @returns
7
+ */
2
8
  export async function rateLimit(args) {
3
- const { team, limitPerSecond, serviceConfig, redis, sampleRate = 1.0, increment = 1, } = args;
4
- const shouldSampleRequest = Math.random() < sampleRate;
5
- if (!shouldSampleRequest) {
6
- return {
7
- rateLimited: false,
8
- requestCount: 0,
9
- rateLimit: 0,
10
- };
11
- }
9
+ const { team, limitPerSecond, serviceConfig, redis, increment = 1 } = args;
10
+ const { serviceScope } = serviceConfig;
12
11
  if (limitPerSecond === 0) {
13
12
  // No rate limit is provided. Assume the request is not rate limited.
14
13
  return {
@@ -17,40 +16,43 @@ export async function rateLimit(args) {
17
16
  rateLimit: 0,
18
17
  };
19
18
  }
20
- const serviceScope = serviceConfig.serviceScope;
21
- // Gets the 10-second window for the current timestamp.
22
- const timestampWindow = Math.floor(Date.now() / (1000 * RATE_LIMIT_WINDOW_SECONDS)) *
23
- RATE_LIMIT_WINDOW_SECONDS;
24
- const key = `rate-limit:${serviceScope}:${team.id}:${timestampWindow}`;
25
- // first read the request count from redis
26
- const requestCount = Number((await redis.get(key).catch(() => "0")) || "0");
27
- // Get the limit for this window accounting for the sample rate.
28
- const limitPerWindow = limitPerSecond * sampleRate * RATE_LIMIT_WINDOW_SECONDS;
29
- if (requestCount > limitPerWindow) {
19
+ // Enforce rate limit: sum the total requests in the last `SLIDING_WINDOW_SECONDS` seconds.
20
+ const currentSecond = Math.floor(Date.now() / 1000);
21
+ const keys = Array.from({ length: SLIDING_WINDOW_SECONDS }, (_, i) => getRequestCountAtSecondCacheKey(serviceScope, team.id, currentSecond - i));
22
+ const counts = await redis.mget(keys);
23
+ const totalCount = counts.reduce((sum, count) => sum + (count ? Number.parseInt(count) : 0), 0);
24
+ const limitPerWindow = limitPerSecond * SLIDING_WINDOW_SECONDS;
25
+ if (totalCount > limitPerWindow) {
30
26
  return {
31
27
  rateLimited: true,
32
- requestCount,
28
+ requestCount: totalCount,
33
29
  rateLimit: limitPerWindow,
34
30
  status: 429,
35
- errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. To get higher rate limits, contact us at https://thirdweb.com/contact-us.`,
31
+ errorMessage: `You've exceeded your ${serviceScope} rate limit at ${limitPerSecond} reqs/sec. Please upgrade your plan to get higher rate limits.`,
36
32
  errorCode: "RATE_LIMIT_EXCEEDED",
37
33
  };
38
34
  }
39
- // do not await this, it just needs to execute at all
40
- (async () =>
41
- // always incrementBy the amount specified for the key
42
- await redis.incrby(key, increment).then(async () => {
43
- // if the initial request count was 0, set the key to expire in the future
44
- if (requestCount === 0) {
45
- await redis.expire(key, RATE_LIMIT_WINDOW_SECONDS);
35
+ // Non-blocking: increment the request count for the current second.
36
+ (async () => {
37
+ try {
38
+ const key = getRequestCountAtSecondCacheKey(serviceScope, team.id, currentSecond);
39
+ await redis.incrby(key, increment);
40
+ // If this is the first time setting this key, expire it after the sliding window is past.
41
+ if (counts[0] === null) {
42
+ await redis.expire(key, SLIDING_WINDOW_SECONDS + 1);
43
+ }
46
44
  }
47
- }))().catch(() => {
48
- console.error("Error incrementing rate limit key", key);
49
- });
45
+ catch (error) {
46
+ console.error("Error updating rate limit key:", error);
47
+ }
48
+ })();
50
49
  return {
51
50
  rateLimited: false,
52
- requestCount: requestCount + increment,
51
+ requestCount: totalCount + increment,
53
52
  rateLimit: limitPerWindow,
54
53
  };
55
54
  }
55
+ function getRequestCountAtSecondCacheKey(serviceScope, teamId, second) {
56
+ return `rate-limit:${serviceScope}:${teamId}:${second}`;
57
+ }
56
58
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":"AAGA,MAAM,yBAAyB,GAAG,EAAE,CAAC;AASrC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAgB/B;IACC,MAAM,EACJ,IAAI,EACJ,cAAc,EACd,aAAa,EACb,KAAK,EACL,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,CAAC,GACd,GAAG,IAAI,CAAC;IAET,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC;IACvD,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,qEAAqE;QACrE,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IAEhD,uDAAuD;IACvD,MAAM,eAAe,GACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,yBAAyB,CAAC,CAAC;QAC3D,yBAAyB,CAAC;IAC5B,MAAM,GAAG,GAAG,cAAc,YAAY,IAAI,IAAI,CAAC,EAAE,IAAI,eAAe,EAAE,CAAC;IAEvE,0CAA0C;IAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAE5E,gEAAgE;IAChE,MAAM,cAAc,GAClB,cAAc,GAAG,UAAU,GAAG,yBAAyB,CAAC;IAE1D,IAAI,YAAY,GAAG,cAAc,EAAE,CAAC;QAClC,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,YAAY;YACZ,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,GAAG;YACX,YAAY,EAAE,wBAAwB,YAAY,kBAAkB,cAAc,sFAAsF;YACxK,SAAS,EAAE,qBAAqB;SACjC,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,CAAC,KAAK,IAAI,EAAE;IACV,uDAAuD;IACvD,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;QACjD,0EAA0E;QAC1E,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,YAAY,GAAG,SAAS;QACtC,SAAS,EAAE,cAAc;KAC1B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":"AAGA,MAAM,sBAAsB,GAAG,EAAE,CAAC;AASlC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAU/B;IACC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IAC3E,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC;IAEvC,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,qEAAqE;QACrE,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,CAAC;YACf,SAAS,EAAE,CAAC;SACb,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnE,+BAA+B,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,aAAa,GAAG,CAAC,CAAC,CAC1E,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1D,CAAC,CACF,CAAC;IAEF,MAAM,cAAc,GAAG,cAAc,GAAG,sBAAsB,CAAC;IAE/D,IAAI,UAAU,GAAG,cAAc,EAAE,CAAC;QAChC,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,UAAU;YACxB,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,GAAG;YACX,YAAY,EAAE,wBAAwB,YAAY,kBAAkB,cAAc,gEAAgE;YAClJ,SAAS,EAAE,qBAAqB;SACjC,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,CAAC,KAAK,IAAI,EAAE;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,+BAA+B,CACzC,YAAY,EACZ,IAAI,CAAC,EAAE,EACP,aAAa,CACd,CAAC;YACF,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACnC,0FAA0F;YAC1F,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,UAAU,GAAG,SAAS;QACpC,SAAS,EAAE,cAAc;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CACtC,YAA+C,EAC/C,MAAc,EACd,MAAc;IAEd,OAAO,cAAc,YAAY,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;AAC1D,CAAC"}
@@ -1,21 +1,21 @@
1
1
  import type { CoreServiceConfig, TeamResponse } from "../api.js";
2
2
  import type { RateLimitResult } from "./types.js";
3
3
  type IRedis = {
4
- get: (key: string) => Promise<string | null>;
5
- expire(key: string, seconds: number): Promise<number>;
6
4
  incrby(key: string, value: number): Promise<number>;
5
+ mget(keys: string[]): Promise<(string | null)[]>;
6
+ expire(key: string, seconds: number): Promise<number>;
7
7
  };
8
+ /**
9
+ * Increments the request count for this team and returns whether the team has hit their rate limit.
10
+ * Uses a sliding 10 second window.
11
+ * @param args
12
+ * @returns
13
+ */
8
14
  export declare function rateLimit(args: {
9
15
  team: TeamResponse;
10
16
  limitPerSecond: number;
11
17
  serviceConfig: CoreServiceConfig;
12
18
  redis: IRedis;
13
- /**
14
- * Sample requests to reduce load on Redis.
15
- * This scales down the request count and the rate limit threshold.
16
- * @default 1.0
17
- */
18
- sampleRate?: number;
19
19
  /**
20
20
  * The number of requests to increment by.
21
21
  * @default 1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,KAAK,MAAM,GAAG;IACZ,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,iBAAiB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,eAAe,CAAC,CAuE3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/rateLimit/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,iBAAiB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4D3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdweb-dev/service-utils",
3
- "version": "0.9.1",
3
+ "version": "0.9.2-nightly-4c1f384a635054a8cfaaa487e3ba7ada63b221ec-20250415110008",
4
4
  "type": "module",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",