@wildix/xbees-conversations-utils 1.1.79 → 1.1.80
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/dist-cjs/rateLimits/helpers/RedisCooldown.js +37 -0
- package/dist-cjs/rateLimits/helpers/executeWithRateLimitHandling.js +4 -2
- package/dist-es/rateLimits/helpers/RedisCooldown.js +37 -0
- package/dist-es/rateLimits/helpers/executeWithRateLimitHandling.js +4 -2
- package/dist-types/rateLimits/helpers/RedisCooldown.d.ts +1 -0
- package/package.json +1 -1
|
@@ -121,6 +121,43 @@ class RedisCooldown {
|
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
+
static async setRemainingMsWithValue(cooldownKey, valueKey, value, cooldownMs, context, options) {
|
|
125
|
+
if (value.length === 0 || cooldownMs <= 0) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const { redis, logger } = context;
|
|
129
|
+
const cooldownRedisKey = RedisCooldown.resolveRedisKey(cooldownKey, options);
|
|
130
|
+
const valueRedisKey = RedisCooldown.resolveRedisKey(valueKey, options);
|
|
131
|
+
try {
|
|
132
|
+
await redis.eval(`
|
|
133
|
+
local cooldown_key = KEYS[1]
|
|
134
|
+
local value_key = KEYS[2]
|
|
135
|
+
local value = ARGV[1]
|
|
136
|
+
local new_ttl = tonumber(ARGV[2])
|
|
137
|
+
local current_ttl = redis.call('PTTL', cooldown_key)
|
|
138
|
+
local final_ttl = new_ttl
|
|
139
|
+
|
|
140
|
+
if current_ttl == -2 then
|
|
141
|
+
redis.call('SET', cooldown_key, '1', 'PX', new_ttl)
|
|
142
|
+
elseif current_ttl == -1 or current_ttl < new_ttl then
|
|
143
|
+
redis.call('PEXPIRE', cooldown_key, new_ttl)
|
|
144
|
+
else
|
|
145
|
+
final_ttl = current_ttl
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
redis.call('SET', value_key, value, 'PX', final_ttl)
|
|
149
|
+
return final_ttl
|
|
150
|
+
`, 2, cooldownRedisKey, valueRedisKey, value, cooldownMs.toString());
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
logger.warn('Failed to write stream rate-limit cooldown and metadata to Redis', {
|
|
154
|
+
cooldownKey,
|
|
155
|
+
valueKey,
|
|
156
|
+
cooldownMs,
|
|
157
|
+
error,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
124
161
|
static async clear(cooldownKey, context, options) {
|
|
125
162
|
const { redis, logger } = context;
|
|
126
163
|
try {
|
|
@@ -106,9 +106,11 @@ async function executeWithRateLimitHandling(execute, operation, context, options
|
|
|
106
106
|
const retryAfterMs = calculateRateLimitDelayMs(rateLimitError, maxDelayMs);
|
|
107
107
|
if (enableCooldown) {
|
|
108
108
|
const rateLimitSnapshot = toRateLimitSnapshot(rateLimitError);
|
|
109
|
-
await RedisCooldown_1.RedisCooldown.setRemainingMs(operation, retryAfterMs, { redis, logger });
|
|
110
109
|
if (rateLimitSnapshot) {
|
|
111
|
-
await RedisCooldown_1.RedisCooldown.
|
|
110
|
+
await RedisCooldown_1.RedisCooldown.setRemainingMsWithValue(operation, getRateLimitMetadataKey(operation), (0, rateLimitSnapshot_1.serializeRateLimitSnapshot)(rateLimitSnapshot), retryAfterMs, { redis, logger });
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
await RedisCooldown_1.RedisCooldown.setRemainingMs(operation, retryAfterMs, { redis, logger });
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
if (attempt < maxAttempts && retryAfterMs <= maxRetryableDelayMs) {
|
|
@@ -118,6 +118,43 @@ export class RedisCooldown {
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
+
static async setRemainingMsWithValue(cooldownKey, valueKey, value, cooldownMs, context, options) {
|
|
122
|
+
if (value.length === 0 || cooldownMs <= 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const { redis, logger } = context;
|
|
126
|
+
const cooldownRedisKey = RedisCooldown.resolveRedisKey(cooldownKey, options);
|
|
127
|
+
const valueRedisKey = RedisCooldown.resolveRedisKey(valueKey, options);
|
|
128
|
+
try {
|
|
129
|
+
await redis.eval(`
|
|
130
|
+
local cooldown_key = KEYS[1]
|
|
131
|
+
local value_key = KEYS[2]
|
|
132
|
+
local value = ARGV[1]
|
|
133
|
+
local new_ttl = tonumber(ARGV[2])
|
|
134
|
+
local current_ttl = redis.call('PTTL', cooldown_key)
|
|
135
|
+
local final_ttl = new_ttl
|
|
136
|
+
|
|
137
|
+
if current_ttl == -2 then
|
|
138
|
+
redis.call('SET', cooldown_key, '1', 'PX', new_ttl)
|
|
139
|
+
elseif current_ttl == -1 or current_ttl < new_ttl then
|
|
140
|
+
redis.call('PEXPIRE', cooldown_key, new_ttl)
|
|
141
|
+
else
|
|
142
|
+
final_ttl = current_ttl
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
redis.call('SET', value_key, value, 'PX', final_ttl)
|
|
146
|
+
return final_ttl
|
|
147
|
+
`, 2, cooldownRedisKey, valueRedisKey, value, cooldownMs.toString());
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger.warn('Failed to write stream rate-limit cooldown and metadata to Redis', {
|
|
151
|
+
cooldownKey,
|
|
152
|
+
valueKey,
|
|
153
|
+
cooldownMs,
|
|
154
|
+
error,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
121
158
|
static async clear(cooldownKey, context, options) {
|
|
122
159
|
const { redis, logger } = context;
|
|
123
160
|
try {
|
|
@@ -103,9 +103,11 @@ export async function executeWithRateLimitHandling(execute, operation, context,
|
|
|
103
103
|
const retryAfterMs = calculateRateLimitDelayMs(rateLimitError, maxDelayMs);
|
|
104
104
|
if (enableCooldown) {
|
|
105
105
|
const rateLimitSnapshot = toRateLimitSnapshot(rateLimitError);
|
|
106
|
-
await RedisCooldown.setRemainingMs(operation, retryAfterMs, { redis, logger });
|
|
107
106
|
if (rateLimitSnapshot) {
|
|
108
|
-
await RedisCooldown.
|
|
107
|
+
await RedisCooldown.setRemainingMsWithValue(operation, getRateLimitMetadataKey(operation), serializeRateLimitSnapshot(rateLimitSnapshot), retryAfterMs, { redis, logger });
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
await RedisCooldown.setRemainingMs(operation, retryAfterMs, { redis, logger });
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
if (attempt < maxAttempts && retryAfterMs <= maxRetryableDelayMs) {
|
|
@@ -6,5 +6,6 @@ export declare class RedisCooldown {
|
|
|
6
6
|
static setRemainingMsExact(cooldownKey: string, cooldownMs: number, context: RedisContext & LoggerContext, options?: RedisCooldownOptions): Promise<void>;
|
|
7
7
|
static getValue(cooldownKey: string, context: RedisContext & LoggerContext, options?: RedisCooldownOptions): Promise<string | undefined>;
|
|
8
8
|
static setValueWithRemainingMs(cooldownKey: string, value: string, cooldownMs: number, context: RedisContext & LoggerContext, options?: RedisCooldownOptions): Promise<void>;
|
|
9
|
+
static setRemainingMsWithValue(cooldownKey: string, valueKey: string, value: string, cooldownMs: number, context: RedisContext & LoggerContext, options?: RedisCooldownOptions): Promise<void>;
|
|
9
10
|
static clear(cooldownKey: string, context: RedisContext & LoggerContext, options?: RedisCooldownOptions): Promise<void>;
|
|
10
11
|
}
|