2026-03-09 14:57:41 +01:00
|
|
|
|
@startuml indexer_heartbeat
|
|
|
|
|
|
title Indexer — Heartbeat node → indexer (score on 5 metrics)
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
|
|
|
|
|
participant "Node A" as NodeA
|
|
|
|
|
|
participant "Node B" as NodeB
|
2026-03-09 14:57:41 +01:00
|
|
|
|
participant "IndexerService" as Indexer
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
note over NodeA,NodeB: Every node tick every 20s (SendHeartbeat)
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
par Node A heartbeat
|
2026-02-24 14:31:37 +01:00
|
|
|
|
NodeA -> Indexer: NewStream /opencloud/heartbeat/1.0
|
2026-03-09 14:57:41 +01:00
|
|
|
|
NodeA -> Indexer: stream.Encode(Heartbeat{Name, PeerID_A, IndexersBinded, Record})
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: CheckHeartbeat(host, stream, dec, streams, mu, maxNodes)
|
|
|
|
|
|
note over Indexer: len(h.Network().Peers()) >= maxNodes → reject
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: getBandwidthChallengeRate(host, remotePeer, 512-2048B)
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: getOwnDiversityRate(host)\\nh.Network().Peers() + Peerstore.Addrs()\\n→ ratio /24 subnets distincts
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: fillRate = len(h.Network().Peers()) / maxNodes
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: Retrieve existing UptimeTracker\\noldTracker.RecordHeartbeat()\\n→ TotalOnline += gap si gap ≤ 120s\\nuptimeRatio = TotalOnline / time.Since(FirstSeen)
|
|
|
|
|
|
|
|
|
|
|
|
Indexer -> Indexer: ComputeIndexerScore(\\n uptimeRatio, bpms, diversity,\\n latencyScore, fillRate\\n)\\nScore = (0.20×U + 0.20×B + 0.20×D + 0.15×L + 0.25×F) × 100
|
|
|
|
|
|
|
|
|
|
|
|
Indexer -> Indexer: dynamicMinScore(age)\\n= 20 + 60×(hours/24), max 80
|
|
|
|
|
|
|
|
|
|
|
|
alt Score A < dynamicMinScore(age)
|
|
|
|
|
|
Indexer -> NodeA: (close stream — "not enough trusting value")
|
|
|
|
|
|
else Score A >= dynamicMinScore(age)
|
|
|
|
|
|
Indexer -> Indexer: streams[PeerID_A].HeartbeatStream = hb.Stream\\nstreams[PeerID_A].HeartbeatStream.UptimeTracker = oldTracker\\nstreams[PeerID_A].LastScore = hb.Score
|
|
|
|
|
|
note over Indexer: AfterHeartbeat → republish PeerRecord on DHT
|
2026-02-24 14:31:37 +01:00
|
|
|
|
end
|
2026-03-09 14:57:41 +01:00
|
|
|
|
|
|
|
|
|
|
else Node B heartbeat
|
2026-02-24 14:31:37 +01:00
|
|
|
|
NodeB -> Indexer: NewStream /opencloud/heartbeat/1.0
|
2026-03-09 14:57:41 +01:00
|
|
|
|
NodeB -> Indexer: stream.Encode(Heartbeat{Name, PeerID_B, IndexersBinded, Record})
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
Indexer -> Indexer: CheckHeartbeat → getBandwidthChallengeRate\\n→ getOwnDiversityRate → ComputeIndexerScore(5 composants)
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
alt Score B >= dynamicMinScore(age)
|
|
|
|
|
|
Indexer -> Indexer: streams[PeerID_B] subscribed + LastScore updated
|
2026-02-24 14:31:37 +01:00
|
|
|
|
end
|
|
|
|
|
|
end par
|
|
|
|
|
|
|
2026-03-09 14:57:41 +01:00
|
|
|
|
note over Indexer: GC ticker 30s — gc()\\nnow.After(Expiry) où Expiry = lastHBTime + 2min\\n→ AfterDelete(pid, name, did)
|
2026-02-24 14:31:37 +01:00
|
|
|
|
|
|
|
|
|
|
@enduml
|