@goodandready/dsh-key-rotation 0.8.47 → 0.8.48
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/CHANGELOG.md +5 -0
- package/lib/webhook.js +20 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.48 - 2026-10-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Debouncer Throttle Interval Preservation & Delivery Guarantee (#428)**: Ensure `AlertDebouncer.prototype.flush` respects `WebhookSender` inter-batch throttling window (`_minIntervalMs`, default 1000ms) between consecutive batch deliveries across high-burst traffic (e.g. 20 rapid exhaustion events splitting into two 10-incident batches), preventing secondary batches from receiving `throttled: true` drops and guaranteeing all accepted digest alerts are delivered without loss.
|
|
7
|
+
|
|
3
8
|
## 0.8.47 - 2026-10-02
|
|
4
9
|
|
|
5
10
|
### Fixed
|
package/lib/webhook.js
CHANGED
|
@@ -265,7 +265,26 @@ export class AlertDebouncer {
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const sendBatch = async () => {
|
|
268
|
-
|
|
268
|
+
if (this._sender && typeof this._sender._lastSentAt?.get === 'function') {
|
|
269
|
+
const last = this._sender._lastSentAt.get(url);
|
|
270
|
+
const minInterval = Number.isFinite(this._sender._minIntervalMs) ? this._sender._minIntervalMs : 1000;
|
|
271
|
+
if (Number.isFinite(last)) {
|
|
272
|
+
const elapsed = Date.now() - last;
|
|
273
|
+
if (elapsed < minInterval) {
|
|
274
|
+
await new Promise((r) => setTimeout(r, minInterval - elapsed + 20));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
let res = await this._sender.send(url, payload);
|
|
279
|
+
while (res && res.throttled) {
|
|
280
|
+
const last = (this._sender && typeof this._sender._lastSentAt?.get === 'function')
|
|
281
|
+
? this._sender._lastSentAt.get(url) : null;
|
|
282
|
+
const minInterval = (this._sender && this._sender._minIntervalMs) || 1000;
|
|
283
|
+
const now = Date.now();
|
|
284
|
+
const wait = Number.isFinite(last) ? Math.max(50, minInterval - (now - last) + 20) : minInterval;
|
|
285
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
286
|
+
res = await this._sender.send(url, payload);
|
|
287
|
+
}
|
|
269
288
|
for (const cb of entry.callbacks) {
|
|
270
289
|
bestEffort('webhook.callback', () => { cb(res); }, this._logger);
|
|
271
290
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-key-rotation",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.48",
|
|
4
4
|
"packageManager": "pnpm@10.33.2",
|
|
5
5
|
"description": "Per-provider API key rotation for DeepSeek Harness: a key pool per provider, auto-created clone routes, and switching to the next key on quota/rate-limit errors. Includes a Settings section (Key Rotation) to edit the key pools, cooldown and switch codes.",
|
|
6
6
|
"keywords": [
|