Skip to content

Commit fda6ab0

Browse files
feat: prioritise most-overdue entries when attaching repair requests
1 parent aedf8e3 commit fda6ab0

2 files changed

Lines changed: 51 additions & 5 deletions

File tree

sds.nim

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import std/[times, locks, tables, sets, options]
1+
import std/[algorithm, times, locks, tables, sets, options]
22
import chronos, results, chronicles
33
import sds/[types, protobuf, sds_utils, rolling_bloom_filter]
44

@@ -89,14 +89,23 @@ proc wrapOutgoingMessage*(
8989
error "Failed to serialize bloom filter", channelId = channelId
9090
return err(ReliabilityError.reSerializationError)
9191

92-
# SDS-R: collect eligible expired repair requests to attach
92+
# SDS-R: collect eligible expired repair requests to attach. Per
93+
# spec (sds-r-send-message, RECOMMENDED), prioritise the entries with
94+
# the smallest minTimeRepairReq — they are the most overdue and the
95+
# ones the network most needs us to ask about.
9396
var repairReqs: seq[HistoryEntry] = @[]
9497
let now = getTime()
9598
var expiredKeys: seq[SdsMessageID] = @[]
99+
var eligible: seq[(SdsMessageID, OutgoingRepairEntry)] = @[]
96100
for msgId, repairEntry in channel.outgoingRepairBuffer:
97-
if now >= repairEntry.minTimeRepairReq and repairReqs.len < rm.config.maxRepairRequests:
98-
repairReqs.add(repairEntry.outHistEntry)
99-
expiredKeys.add(msgId)
101+
if now >= repairEntry.minTimeRepairReq:
102+
eligible.add((msgId, repairEntry))
103+
eligible.sort do(a, b: (SdsMessageID, OutgoingRepairEntry)) -> int:
104+
cmp(a[1].minTimeRepairReq, b[1].minTimeRepairReq)
105+
let take = min(eligible.len, rm.config.maxRepairRequests)
106+
for i in 0 ..< take:
107+
repairReqs.add(eligible[i][1].outHistEntry)
108+
expiredKeys.add(eligible[i][0])
100109
for key in expiredKeys:
101110
channel.outgoingRepairBuffer.del(key)
102111

tests/test_reliability.nim

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,43 @@ suite "SDS-R: Repair Buffer Management":
11481148
# Should be removed from buffer after attaching
11491149
"missing-msg" notin channel.outgoingRepairBuffer
11501150

1151+
test "expired repair requests attach the most-overdue first when capped":
1152+
# Per spec (sds-r-send-message, RECOMMENDED): when more entries are
1153+
# eligible than maxRepairRequests, attach the ones with the smallest
1154+
# minTimeRepairReq — i.e. the most overdue.
1155+
rm.setCallbacks(
1156+
proc(messageId: SdsMessageID, channelId: SdsChannelID) {.gcsafe.} = discard,
1157+
proc(messageId: SdsMessageID, channelId: SdsChannelID) {.gcsafe.} = discard,
1158+
proc(messageId: SdsMessageID, missingDeps: seq[HistoryEntry], channelId: SdsChannelID) {.gcsafe.} = discard,
1159+
)
1160+
let channel = rm.channels[testChannel]
1161+
let now = getTime()
1162+
1163+
# Five eligible entries with strictly ordered minTimeRepairReq (most-overdue first).
1164+
# All are expired; the cap is the default 3, so two should be left behind.
1165+
let expected = ["oldest", "second", "third", "fourth", "newest"]
1166+
for i, id in expected:
1167+
channel.outgoingRepairBuffer[id] = OutgoingRepairEntry(
1168+
outHistEntry: HistoryEntry(messageId: id, senderId: "sender"),
1169+
minTimeRepairReq: now - initDuration(seconds = 50 - i * 10),
1170+
)
1171+
1172+
let wrapped = rm.wrapOutgoingMessage(@[byte(1)], "outbound", testChannel)
1173+
check wrapped.isOk()
1174+
1175+
let attached = deserializeMessage(wrapped.get()).get().repairRequest
1176+
check:
1177+
attached.len == rm.config.maxRepairRequests
1178+
attached[0].messageId == "oldest"
1179+
attached[1].messageId == "second"
1180+
attached[2].messageId == "third"
1181+
# Two least-overdue remain in the buffer for next time.
1182+
"fourth" in channel.outgoingRepairBuffer
1183+
"newest" in channel.outgoingRepairBuffer
1184+
"oldest" notin channel.outgoingRepairBuffer
1185+
"second" notin channel.outgoingRepairBuffer
1186+
"third" notin channel.outgoingRepairBuffer
1187+
11511188
test "incoming repair request adds to incoming repair buffer when eligible":
11521189
rm.setCallbacks(
11531190
proc(messageId: SdsMessageID, channelId: SdsChannelID) {.gcsafe.} = discard,

0 commit comments

Comments
 (0)