on master help sign in
Fix bug #8: order forward backlog by receivedAt before clipping to budget

forwardQueuedToServer filtered candidate messages from *messages (a set in Knot) then took the first `budget` to enqueue as forwards. With no ordering, an implementation-defined subset was chosen — when the backlog exceeded maxForwardsPerServer, newer messages could be forwarded while older ones were skipped indefinitely. Sort candidates by receivedAt ascending before take, matching the pattern already used in doPoll.

commit1f0ce2ec3dd338a50e706a3ca30082d830032f8e authoriko <mail@iko.soy> dateFri 29 May 2026, 19:07 (4 months ago) parent9649de9
1 file changed+1−1
server.knot+1−1
server.knot+1−1
@@ -585,7 +585,7 @@ forwardQueuedToServer = \pubkey server -> atomic (do
585585 let existing = count (filter (\f -> f.toServer == server) fwds)
586586 let budget = max 0 (maxForwardsPerServer - existing)
587587 let candidates = filter (\m -> m.toKey == pubkey && not any (forwardMatches m.encryptedBlob server) fwds && not elem server m.deliveredTo) msgs
588− let newFwds = map (\m -> {toServer: server, m.toKey, m.encryptedBlob, retries: 0}) (take budget candidates)
588+ let newFwds = map (\m -> {toServer: server, m.toKey, m.encryptedBlob, retries: 0}) (take budget (sortBy (\m -> m.receivedAt) candidates))
589589 *forwards = union fwds newFwds)
590590
591591-- ============================================