mirror of
https://github.com/telemt/telemt.git
synced 2026-11-02 05:42:00 +03:00
Retry Jitter
This commit is contained in:
@@ -1,5 +1,21 @@
|
||||
(()=>{'use strict';
|
||||
function create(settings){
|
||||
// Snapshot policy per page, including during session recovery.
|
||||
const jitter=Object.freeze(Object.assign({},settings.jitter||{enabled:false}));
|
||||
const randomWord=jitter.enabled?new Uint32Array(1):null;
|
||||
function randomUnit(){
|
||||
try{if(globalThis.crypto&&typeof globalThis.crypto.getRandomValues==='function'){
|
||||
globalThis.crypto.getRandomValues(randomWord);return randomWord[0]/4294967296;
|
||||
}}catch(error){}
|
||||
return Math.random();
|
||||
}
|
||||
function jitterMs(){
|
||||
const a=jitter.min,b=jitter.max;if(a===b)return a;
|
||||
const u=randomUnit();
|
||||
if(!jitter.triangular)return a+Math.floor(u*(b-a+1));
|
||||
const c=jitter.peak,span=b-a;
|
||||
return Math.round(u<(c-a)/span?a+Math.sqrt(u*span*(c-a)):b-Math.sqrt((1-u)*span*(b-c)));
|
||||
}
|
||||
const pause=(milliseconds,signal)=>new Promise((resolve,reject)=>{
|
||||
if(signal&&signal.aborted){reject(new Error('request aborted'));return}
|
||||
const timer=setTimeout(done,milliseconds);function done(){if(signal)signal.removeEventListener('abort',abort);resolve()}
|
||||
@@ -15,10 +31,12 @@ function create(settings){
|
||||
// Only the exact Telemt overload hint overrides its legacy whole-second fallback.
|
||||
if(response.status===503&&header==='1'&&response.headers.get('X-Telemt-Retry-After-Ms')==='250')return 250;
|
||||
if(!header)return 0;
|
||||
// Enabled policies must never shorten a valid server minimum to the legacy 30 s cap.
|
||||
if(jitter.enabled&&/^\d+$/.test(header))return Number(header)*1000;
|
||||
const seconds=Number(header);
|
||||
if(Number.isFinite(seconds)&&seconds>=0)return Math.min(seconds*1000,30000);
|
||||
if(Number.isFinite(seconds)&&seconds>=0)return jitter.enabled?seconds*1000:Math.min(seconds*1000,30000);
|
||||
const when=Date.parse(header);
|
||||
if(Number.isFinite(when)){const delta=when-Date.now();return delta>0?Math.min(delta,30000):0}
|
||||
if(Number.isFinite(when)){const delta=when-Date.now();return delta>0?(jitter.enabled?delta:Math.min(delta,30000)):0}
|
||||
return 0;
|
||||
}
|
||||
function retryableStatus(status){return status===408||status===429||status===502||status===503||status===504}
|
||||
@@ -65,7 +83,7 @@ function create(settings){
|
||||
}finally{clearTimeout(timer);if(external)external.removeEventListener('abort',abort)}
|
||||
const after=Math.min(deadline-Date.now(),remainingBudget?remainingBudget():Infinity);if(attempt>=attempts()||after<=0)break;
|
||||
settings.retrying();
|
||||
const backoff=wait||delay+Math.floor(Math.random()*Math.max(1,delay/4));
|
||||
const backoff=jitter.enabled?(wait||delay)+jitterMs():wait||delay+Math.floor(Math.random()*Math.max(1,delay/4));
|
||||
await pause(Math.min(backoff,after),external);delay=Math.min(delay*2,2000);
|
||||
}
|
||||
throw settings.failure(lastReason,'carrier retry limit reached');
|
||||
|
||||
Reference in New Issue
Block a user