@wildix/xbees-conversations-utils 1.2.10 → 1.3.1
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.
- package/README.md +13 -113
- package/dist-cjs/index.js +0 -1
- package/dist-es/index.js +0 -1
- package/dist-types/index.d.ts +0 -1
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -1,118 +1,18 @@
|
|
|
1
|
-
# `
|
|
1
|
+
# `xbees-conversations-utils`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utility helpers for working with x-bees conversations data.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Included modules
|
|
6
6
|
|
|
7
|
-
- `
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
7
|
+
- `anonymousEmail`
|
|
8
|
+
Helpers for generating and validating anonymous user emails.
|
|
9
|
+
- `normalization`
|
|
10
|
+
Helpers for normalizing and localizing Stream payloads into `@wildix/xbees-conversations-client` models.
|
|
11
|
+
- `stream`
|
|
12
|
+
Shared Stream Chat types used by normalization helpers and downstream consumers.
|
|
13
|
+
- `types`
|
|
14
|
+
Localized conversation and presence-related TypeScript types.
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## Notes
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
2. The proxy classifies Stream methods into groups generated in `generatedMethodNames.ts`:
|
|
19
|
-
- pure sync methods: returned as-is;
|
|
20
|
-
- sync methods returning channel/client objects: returned sync, but results are re-wrapped;
|
|
21
|
-
- async methods: executed through the rate-limit handler.
|
|
22
|
-
3. Every async call is normalized through `executeWithRateLimitHandling(...)`.
|
|
23
|
-
4. Returned channel-like objects are detected and wrapped again, so calls like `stream.channel(...).sendMessage(...)` stay protected end to end.
|
|
24
|
-
|
|
25
|
-
If the underlying Stream SDK transport does not expose an axios instance, the proxy still works, but shared protection driven by response headers becomes less effective because no interceptors can be attached.
|
|
26
|
-
|
|
27
|
-
## Protection layers
|
|
28
|
-
|
|
29
|
-
### 1. Soft global throttle
|
|
30
|
-
|
|
31
|
-
The interceptor reads `x-ratelimit-limit` and `x-ratelimit-remaining`. When usage becomes high, it enables a short shared Redis cooldown before real 429 responses start happening. This smooths bursts instead of waiting for hard throttling.
|
|
32
|
-
|
|
33
|
-
- Trigger source: response headers on successful or failed requests
|
|
34
|
-
- Effect:
|
|
35
|
-
- usage `>= 95%`: delay next requests by `3000ms`;
|
|
36
|
-
- usage between `85%` and `95%`: delay by `1500ms`;
|
|
37
|
-
- usage between `70%` and `85%`: delay by `500ms`;
|
|
38
|
-
- usage `< 70%`: clear soft throttle.
|
|
39
|
-
- Scope: global shared throttle
|
|
40
|
-
- Code: `helpers/processStreamRateLimitHeaders.ts`
|
|
41
|
-
|
|
42
|
-
### 2. Hard per-operation 429 cooldown
|
|
43
|
-
|
|
44
|
-
If Stream returns HTTP 429, the handler converts that error into `RateLimitExceededException`, calculates retry delay from `retry-after` or fallback values, stores a Redis cooldown for the specific operation, and optionally retries the call.
|
|
45
|
-
|
|
46
|
-
If another worker hits the same operation while that cooldown is still active, the request is short-circuited locally before touching Stream. To keep that synthetic error useful, the latest real `x-ratelimit-*` snapshot is cached in Redis next to the cooldown and reused in the locally generated exception.
|
|
47
|
-
|
|
48
|
-
- Trigger source: HTTP 429 / `retry-after` / `x-ratelimit-*`
|
|
49
|
-
- Effect: per-operation block, optional retry, synthetic local short-circuit when cooldown is already known
|
|
50
|
-
- Scope: operation-level
|
|
51
|
-
- Code:
|
|
52
|
-
- execution flow: `helpers/executeWithRateLimitHandling.ts`
|
|
53
|
-
- 429 parsing: `helpers/processStreamRateLimitException.ts`
|
|
54
|
-
- exception creation: `helpers/createRateLimitExceededException.ts`
|
|
55
|
-
- snapshot serialization: `helpers/rateLimitSnapshot.ts`
|
|
56
|
-
|
|
57
|
-
### 3. App-wide budget cooldown
|
|
58
|
-
|
|
59
|
-
The interceptor also reads `x-budget-*` headers. If overall Stream app budget usage becomes high, it enables a global Redis cooldown. While this cooldown is active, requests are delayed in small sleep chunks so they can resume early if a fresher response lowers the cooldown.
|
|
60
|
-
|
|
61
|
-
- Trigger source: `x-budget-limit-ms`, `x-budget-remaining-ms`, `x-budget-used-ms`
|
|
62
|
-
- Effect:
|
|
63
|
-
- usage `>= 80%`: enable strong cooldown (`30s-60s`);
|
|
64
|
-
- usage between `70%` and `80%`: keep a relaxed cooldown (`5s-10s`);
|
|
65
|
-
- usage between `60%` and `70%`: keep a minimal cooldown (`1s-2s`);
|
|
66
|
-
- usage `< 60%`: clear cooldown.
|
|
67
|
-
- Scope: whole application, not a single operation
|
|
68
|
-
- Code: `helpers/processStreamBudgetHeaders.ts`
|
|
69
|
-
|
|
70
|
-
## Retry and cooldown behavior
|
|
71
|
-
|
|
72
|
-
- Local preflight checks happen before request execution when `enableCooldown` is on:
|
|
73
|
-
- active per-operation cooldown: fail fast with a synthetic `RateLimitExceededException`;
|
|
74
|
-
- active soft throttle: delay request briefly;
|
|
75
|
-
- active budget cooldown: delay request globally.
|
|
76
|
-
- Real 429 responses can still be retried if:
|
|
77
|
-
- `attempt < maxAttempts`;
|
|
78
|
-
- computed delay `<= maxRetryableDelayMs`.
|
|
79
|
-
- Delay calculation rules:
|
|
80
|
-
- if Stream provides `Retry-After` / reset information, that server value is preferred even if it is larger than `maxDelayMs`;
|
|
81
|
-
- `maxDelayMs` only caps fallback delay when server retry timing is missing or malformed;
|
|
82
|
-
- `maxRetryableDelayMs` decides whether that computed delay is still retryable or should be propagated immediately.
|
|
83
|
-
- If retry is not allowed, the processed rate-limit exception is propagated to the caller.
|
|
84
|
-
|
|
85
|
-
Core logic: `src/streamRateLimitHandlingProxy/helpers/executeWithRateLimitHandling.ts`
|
|
86
|
-
|
|
87
|
-
## Configuration
|
|
88
|
-
|
|
89
|
-
Default behavior is defined in `src/streamRateLimitHandlingProxy/constants.ts`:
|
|
90
|
-
|
|
91
|
-
- `maxAttempts = 3`
|
|
92
|
-
- `enableCooldown = true`
|
|
93
|
-
- `maxDelayMs = 5000`
|
|
94
|
-
- `maxRetryableDelayMs = 10000`
|
|
95
|
-
|
|
96
|
-
The same file also contains:
|
|
97
|
-
|
|
98
|
-
- Redis key prefixes for hard cooldown, soft throttle, and budget cooldown
|
|
99
|
-
- fallback retry values and jitter
|
|
100
|
-
- budget thresholds and cooldown ranges
|
|
101
|
-
- soft-throttle thresholds and delays
|
|
102
|
-
|
|
103
|
-
Notes:
|
|
104
|
-
|
|
105
|
-
- `enableCooldown` controls local Redis-based preflight checks and shared cooldown reuse.
|
|
106
|
-
- `maxDelayMs` is a fallback cap, not a hard upper bound for server-provided `Retry-After`.
|
|
107
|
-
- Missing / invalid rate-limit headers do not break the proxy, but they reduce how much shared throttling state can be inferred.
|
|
108
|
-
|
|
109
|
-
Per-call overrides are passed as the last argument:
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
stream.queryChannels(filters, sort, options, withStreamRateLimitOptions({
|
|
113
|
-
maxAttempts: 1,
|
|
114
|
-
maxRetryableDelayMs: 0,
|
|
115
|
-
}));
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Argument extraction is implemented in `helpers/splitCallArgsAndOptions.ts`.
|
|
18
|
+
The Stream rate-limit handling proxy was moved into the dedicated `@wildix/stream-proxy` package.
|
package/dist-cjs/index.js
CHANGED
|
@@ -4,5 +4,4 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
tslib_1.__exportStar(require("./anonymousEmail"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./normalization"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./stream"), exports);
|
|
7
|
-
tslib_1.__exportStar(require("./streamRateLimitHandlingProxy"), exports);
|
|
8
7
|
tslib_1.__exportStar(require("./types"), exports);
|
package/dist-es/index.js
CHANGED
package/dist-types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wildix/xbees-conversations-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist-cjs/index.js",
|
|
6
6
|
"module": "./dist-es/index.js",
|
|
7
7
|
"types": "./dist-types/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"prebuild": "node ./scripts/generateRateLimitMethodNames.mjs",
|
|
10
9
|
"build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
|
|
11
10
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
12
11
|
"build:es": "tsc -p tsconfig.es.json",
|
|
@@ -25,9 +24,7 @@
|
|
|
25
24
|
},
|
|
26
25
|
"license": "Apache-2.0",
|
|
27
26
|
"dependencies": {
|
|
28
|
-
"@aws-lambda-powertools/logger": "2.18.0",
|
|
29
27
|
"@wildix/xbees-conversations-client": "1.2.13",
|
|
30
|
-
"ioredis": "5.10.0",
|
|
31
28
|
"stream-chat": "8.12.1",
|
|
32
29
|
"tslib": "2.5.0"
|
|
33
30
|
},
|