fix(optimizer): правильно сопоставить направления DL и UL
This commit is contained in:
1 parent
7d331aff41
commit
4ba7f82ccf
6 files changed
+74
-17
No files matched your search
+20
-12
@@ -52,8 +52,14 @@ export interface OptimizerObservedMetrics {
|
||||
pingAt: string | null
|
||||
}
|
||||
|
||||
export function readOptimizerObservedMetrics(probe?: RouteOptimizerSpeedProbe): OptimizerObservedMetrics {
|
||||
return {probeId:probe?.id ?? null,pingMs:probe?.lastPingRttMs ?? null,lossPct:probe?.lastPingLossPct ?? null,dlMbps:probe?.lastTxAvgMbps ?? null,ulMbps:probe?.lastRxAvgMbps ?? null,pingAt:probe?.lastPingAt ?? null}
|
||||
/** DL points toward Home, UL away from Home; TX/RX belong to the btest client. */
|
||||
export function readOptimizerObservedMetrics(probe?: RouteOptimizerSpeedProbe, clientOnFarSide = false): OptimizerObservedMetrics {
|
||||
return {
|
||||
probeId:probe?.id ?? null,pingMs:probe?.lastPingRttMs ?? null,lossPct:probe?.lastPingLossPct ?? null,
|
||||
dlMbps:(clientOnFarSide ? probe?.lastTxAvgMbps : probe?.lastRxAvgMbps) ?? null,
|
||||
ulMbps:(clientOnFarSide ? probe?.lastRxAvgMbps : probe?.lastTxAvgMbps) ?? null,
|
||||
pingAt:probe?.lastPingAt ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
export interface WanJhLeg {
|
||||
@@ -485,22 +491,23 @@ export function buildLiveOptimizerData(
|
||||
const jhRow = byId.get(jh.id)
|
||||
const jhOnline = jhRow?.status === "online"
|
||||
const probe = assignedByWanId.get(wan.id)
|
||||
const observed = readOptimizerObservedMetrics(probe)
|
||||
const modelPing = legPing(homeLat, jhRow?.latency ?? null, homeOnline, !!jhOnline)
|
||||
const ping = probe?.lastPingRttMs != null
|
||||
? Math.max(1, Math.round(probe.lastPingRttMs))
|
||||
: modelPing
|
||||
const modelBw = legBandwidthMbps(ping, wan.maxDl, wan.maxUl)
|
||||
const dl = probe?.lastTxAvgMbps != null
|
||||
? Math.max(1, Math.min(wan.maxDl, Math.round(probe.lastTxAvgMbps)))
|
||||
const dl = observed.dlMbps !== null
|
||||
? Math.max(1, Math.min(wan.maxDl, Math.round(observed.dlMbps)))
|
||||
: modelBw.dl
|
||||
const ul = probe?.lastRxAvgMbps != null
|
||||
? Math.max(1, Math.min(wan.maxUl, Math.round(probe.lastRxAvgMbps)))
|
||||
const ul = observed.ulMbps !== null
|
||||
? Math.max(1, Math.min(wan.maxUl, Math.round(observed.ulMbps)))
|
||||
: modelBw.ul
|
||||
const loss = probe?.lastPingLossPct != null
|
||||
? Math.max(0, Math.min(100, Math.round(probe.lastPingLossPct)))
|
||||
: (!homeOnline || !jhOnline ? 100 : 0)
|
||||
wanJhLegs.push({
|
||||
observed: readOptimizerObservedMetrics(probe),
|
||||
observed,
|
||||
wanId: wan.id,
|
||||
jhId: jh.id,
|
||||
pingMs: ping,
|
||||
@@ -528,19 +535,20 @@ export function buildLiveOptimizerData(
|
||||
const exRow = byId.get(ex.id)
|
||||
const ok = jhRow?.status === "online" && exRow?.status === "online"
|
||||
const probe = pickProbeForJhExit(jh.id, ex.id)
|
||||
const observed = readOptimizerObservedMetrics(probe, probe?.srcServerId === ex.id)
|
||||
const modelPing = legPing(jhRow?.latency ?? null, exRow?.latency ?? null, !!ok, !!ok)
|
||||
const ping = probe?.lastPingRttMs != null
|
||||
? Math.max(1, Math.round(probe.lastPingRttMs))
|
||||
: modelPing
|
||||
const modelBw = legBandwidthMbps(ping, 1000, 1000)
|
||||
const dl = probe?.lastTxAvgMbps != null
|
||||
? Math.max(1, Math.round(probe.lastTxAvgMbps))
|
||||
const dl = observed.dlMbps !== null
|
||||
? Math.max(1, Math.round(observed.dlMbps))
|
||||
: modelBw.dl
|
||||
const ul = probe?.lastRxAvgMbps != null
|
||||
? Math.max(1, Math.round(probe.lastRxAvgMbps))
|
||||
const ul = observed.ulMbps !== null
|
||||
? Math.max(1, Math.round(observed.ulMbps))
|
||||
: modelBw.ul
|
||||
jhExMap.set(`${jh.id}::${ex.id}`, {
|
||||
observed: readOptimizerObservedMetrics(probe),
|
||||
observed,
|
||||
jhId: jh.id,
|
||||
exitId: ex.id,
|
||||
pingMs: ping,
|
||||
|
||||
@@ -7,10 +7,10 @@ test("observed raw zero, decimal, null and old receipt stay separate from model
|
||||
const result=buildLiveOptimizerData(rows,[],DEFAULT_ROUTE_AI_OPTIMIZER_SETTINGS,[probe,{...probe,id:"e",srcServerId:"2",dstServerId:"3",lastTxAvgMbps:0}])
|
||||
const leg=result.homes[0].wanJhLegs[0],exit=result.homes[0].fullRoutes[0].je
|
||||
assert.equal(leg.pingMs,1);assert.equal(leg.dlMbps,100)
|
||||
assert.equal(leg.observed?.pingMs,0);assert.equal(leg.observed?.dlMbps,150.25);assert.equal(leg.observed?.ulMbps,null)
|
||||
assert.equal(leg.observed?.pingMs,0);assert.equal(leg.observed?.ulMbps,150.25);assert.equal(leg.observed?.dlMbps,null)
|
||||
assert.equal(leg.observed?.lossPct,0);assert.equal(leg.observed?.pingAt,"2020-01-01T00:00:00Z")
|
||||
assert.equal(leg.score,calcRouteScore(leg.pingMs,leg.dlMbps,leg.ulMbps,60))
|
||||
assert.equal(exit.pingMs,1);assert.equal(exit.observed?.pingMs,0);assert.equal(exit.observed?.dlMbps,0)
|
||||
assert.equal(exit.pingMs,1);assert.equal(exit.observed?.pingMs,0);assert.equal(exit.observed?.ulMbps,0)
|
||||
})
|
||||
test("missing and disabled probe leave observed values unknown while model stays available",()=>{
|
||||
for(const probes of [[],[{...probe,enabled:false}]]){
|
||||
@@ -50,3 +50,27 @@ test("Community catalog retains all 1000 source rules without inventing indices"
|
||||
assert.equal(recs.length,1000);assert.equal(recs[999].community,'65001:1000')
|
||||
assert.ok(recs.every(rec=>rec.current===null&&rec.recommended===null&&!rec.shouldSwitch))
|
||||
})
|
||||
|
||||
|
||||
test("forward and reversed peer tests keep DL toward Home and UL away, with asymmetric WAN limits",()=>{
|
||||
const inventory=rows.map((row,i)=>i===0?{...row,wanUplinks:[{id:'w',name:'WAN',iface:'ether1',isp:'ISP',ip:'198.51.100.1',maxDl:100,maxUl:20}]}:row)
|
||||
const home={...probe,lastPingRttMs:5,lastTxAvgMbps:30,lastRxAvgMbps:80}
|
||||
const forward={...probe,id:'peer',srcServerId:'2',dstServerId:'3',srcInterface:'',lastPingRttMs:5,lastTxAvgMbps:40,lastRxAvgMbps:90}
|
||||
const reverse={...forward,srcServerId:'3',dstServerId:'2',lastTxAvgMbps:90,lastRxAvgMbps:40}
|
||||
for(const peer of [forward,reverse]){
|
||||
const entry=buildLiveOptimizerData(inventory,[],DEFAULT_ROUTE_AI_OPTIMIZER_SETTINGS,[home,peer]).homes[0],route=entry.fullRoutes[0]
|
||||
assert.equal(route.hw.observed?.dlMbps,80);assert.equal(route.hw.observed?.ulMbps,30)
|
||||
assert.equal(route.hw.dlMbps,80);assert.equal(route.hw.ulMbps,20)
|
||||
assert.equal(route.je.observed?.dlMbps,90);assert.equal(route.je.observed?.ulMbps,40)
|
||||
assert.equal(route.je.dlMbps,90);assert.equal(route.je.ulMbps,40)
|
||||
assert.equal(route.score,calcRouteScore(10,80,20,60))
|
||||
}
|
||||
})
|
||||
|
||||
test("reversed probe keeps measured zero and missing rate distinct",()=>{
|
||||
const reversed={...probe,lastTxAvgMbps:0,lastRxAvgMbps:null}
|
||||
assert.equal(readOptimizerObservedMetrics(reversed,true).dlMbps,0)
|
||||
assert.equal(readOptimizerObservedMetrics(reversed,true).ulMbps,null)
|
||||
assert.equal(readOptimizerObservedMetrics(reversed).dlMbps,null)
|
||||
assert.equal(readOptimizerObservedMetrics(reversed).ulMbps,0)
|
||||
})
|
||||
Reference in new issue
Block a user