Commitf80b2450Recorded5 Aug 2026Repositoryapiary
Make the confirmation decision reachable by a test
Message
Sabotaging the wait loop back to keying on absence - the HIGH the previous commit fixed - left all 132 tests green. The fix was real; the gate for it was not, because the loop sits past send-ping! and so needs a live socket, and nothing could reach the decision inside it.
confirm-verdict is that decision, named and exported, with the loop reduced to repeating it. Four tests now drive it directly, including the abandoned-token case, its positive control (a genuine PONG must still read as confirmed, or a verdict that never confirms would pass for free), and the ordering that keeps evidence which already arrived from being retracted by a link that dropped afterwards.
Changed
src/apiary/enclave.sgl | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
test/test-enclave.sgl | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 33 deletions(-)Diff
src/apiary/enclave.sglmodified
@@ -91,6 +91,7 @@
91
enclave-conn-ping-waiting? 92
enclave-conn-ping-acked? 93
enclave-conn-acked-pings+94
confirm-verdict 95
enclave-conn-pings-clear! 96
enclave-conn-ping-outstanding? 97
enclave-conn-oldest-ping-ts@@ -2023,6 +2024,40 @@
2024
;; Public: channel posting + watchers 2025
;; ============================================================ 2026
+2027
;;; One step of the confirmation wait: has this token been+2028
;;; settled, and how? Returns 'wait while the answer is still+2029
;;; genuinely unknown.+2030
;;;+2031
;;; Extracted from the wait loop so it can be tested WITHOUT a+2032
;;; live connection. That is not tidiness: the loop is only+2033
;;; reachable past `send-ping!`, which needs a real socket, so+2034
;;; while this decision lived inline NOTHING could exercise it —+2035
;;; and a sabotage reverting it to key on absence (the HIGH this+2036
;;; file already carries a comment about) left the entire unit+2037
;;; suite green. A decision this load-bearing has to be reachable+2038
;;; by a test.+2039
;;;+2040
;;; Order matters. POSITIVE evidence is checked FIRST, so a PONG+2041
;;; that genuinely arrived is honoured even if the link dropped+2042
;;; immediately afterwards.+2043
(define (confirm-verdict conn token irc-at-write deadline)+2044
(: enclave-conn? string? any? number? -> symbol?)+2045
(cond+2046
;; The peer answered THIS token. Not "the token left the+2047
;; outstanding list" — see `enclave-conn-ping-acked?`.+2048
((enclave-conn-ping-acked? conn token) 'confirmed)+2049
;; The link is known bad, so no answer is coming — and the+2050
;; token may well have been cleared without one.+2051
((or (enclave-conn-shutdown? conn)+2052
(enclave-conn-reconnecting? conn))+2053
'link-down)+2054
;; The socket we wrote to has been replaced.+2055
((and irc-at-write+2056
(not (eq? irc-at-write (enclave-conn-irc conn))))+2057
'link-changed)+2058
((> (current-second) deadline) 'unconfirmed)+2059
(else 'wait)))+2060
2061
;;; Ask the peer to prove it consumed what we just wrote. 2062
;;; 2063
;;; Returns `'confirmed`, `'unconfirmed`, or `'not-ready`.@@ -2111,39 +2146,29 @@
2146
(else 2147
(let ((deadline (+ (current-second) +post-confirm-timeout+))) 2148
(let wait ()−2114
(cond−2115
;; POSITIVE evidence only. NOT "the token left−2116
;; the outstanding list" — see−2117
;; `enclave-conn-ping-acked?` for why that is a−2118
;; different and much weaker claim.−2119
((enclave-conn-ping-acked? conn token)−2120
(log-debug "Apiary post-confirm confirmed"−2121
elapsed-ms:−2122
(number->string−2123
(round (* 1000 (- (current-second) now)))))−2124
'confirmed)−2125
;; Give up early once the link is known bad.−2126
;; Belt and braces on top of the acked-token−2127
;; check: neither alone is sufficient, because a−2128
;; flag can be set and cleared again between two−2129
;; wakeups.−2130
((or (enclave-conn-shutdown? conn)−2131
(enclave-conn-reconnecting? conn))−2132
'link-down)−2133
((and irc-at-write−2134
(not (eq? irc-at-write (enclave-conn-irc conn))))−2135
'link-changed)−2136
((> (current-second) deadline)−2137
(log-warn "Apiary post-confirm UNCONFIRMED — no PONG within budget"−2138
budget-sec:−2139
(number->string +post-confirm-timeout+))−2140
'unconfirmed)−2141
(else−2142
;; Yields to the cooperative scheduler so the−2143
;; event-loop goroutine can read the socket and−2144
;; ack our token.−2145
(sleep +post-confirm-poll+)−2146
(wait))))))))))))+2149
(let ((verdict (confirm-verdict conn token irc-at-write+2150
deadline)))+2151
(cond+2152
((not (eq? verdict 'wait))+2153
(cond+2154
((eq? verdict 'confirmed)+2155
(log-debug "Apiary post-confirm confirmed"+2156
elapsed-ms:+2157
(number->string+2158
(round (* 1000 (- (current-second)+2159
now))))))+2160
((eq? verdict 'unconfirmed)+2161
(log-warn "Apiary post-confirm UNCONFIRMED — no PONG within budget"+2162
budget-sec:+2163
(number->string+2164
+post-confirm-timeout+))))+2165
verdict)+2166
(else+2167
;; Yields to the cooperative scheduler so the+2168
;; event-loop goroutine can read the socket+2169
;; and ack our token.+2170
(sleep +post-confirm-poll+)+2171
(wait))))))))))))) 2172
2173
;;; Send a PRIVMSG to a channel (or any target). Always uses the 2174
;;; `:trailing` form for the body so single-token messages liketest/test-enclave.sglmodified
@@ -383,6 +383,58 @@
383
(assert-false (enclave-conn-ping-waiting? c "apk-abandoned")) 384
(assert-false (enclave-conn-ping-acked? c "apk-abandoned")))) 385
+386
;; ---- the confirmation wait's own decision ------------------+387
;;+388
;; These drive `confirm-verdict`, which is the step the wait loop+389
;; repeats. It exists as a named procedure precisely so it can be+390
;; reached from here: the loop itself sits past `send-ping!`, which+391
;; needs a real socket, so while this decision was inline a+392
;; sabotage reverting it to key on ABSENCE left the whole suite+393
;; green. Verified by re-running that sabotage against these.+394
+395
(test "confirm-verdict: an ABANDONED token is not confirmation"+396
;; The HIGH. A reconnect during the wait clears the outstanding+397
;; list without any PONG. Keying on absence read that as delivery+398
;; and reported success for a message written to a socket being+399
;; abandoned at that moment.+400
(let ((c (enclave-conn irc: 'sock config: (enclave-config)))+401
(far (+ (current-second) 60)))+402
(enclave-conn-ping-add! c "apk-t" (current-second))+403
(assert-equal 'wait (confirm-verdict c "apk-t" 'sock far))+404
(enclave-conn-pings-clear! c) ;; what trigger-reconnect! does+405
(assert-false (eq? 'confirmed (confirm-verdict c "apk-t" 'sock far)))))+406
+407
(test "confirm-verdict: a genuine PONG IS confirmation"+408
;; Positive control for the test above. Without it, a verdict+409
;; procedure that NEVER says 'confirmed would pass for free.+410
(let ((c (enclave-conn irc: 'sock config: (enclave-config)))+411
(far (+ (current-second) 60)))+412
(enclave-conn-ping-add! c "apk-t" (current-second))+413
(assert-true (enclave-conn-ping-ack! c "apk-t"))+414
(assert-equal 'confirmed (confirm-verdict c "apk-t" 'sock far))))+415
+416
(test "confirm-verdict: a real PONG wins over a link that then dropped"+417
;; Ordering. Evidence that already arrived is not retracted by+418
;; the link failing a moment later, or a post confirmed on a+419
;; healthy socket would be reported unconfirmed whenever the+420
;; connection dropped just afterwards.+421
(let ((c (enclave-conn irc: 'sock config: (enclave-config)))+422
(far (+ (current-second) 60)))+423
(enclave-conn-ping-add! c "apk-t" (current-second))+424
(enclave-conn-ping-ack! c "apk-t")+425
(set-enclave-conn-reconnecting?! c #t)+426
(assert-equal 'confirmed (confirm-verdict c "apk-t" 'sock far))))+427
+428
(test "confirm-verdict: the other outcomes"+429
(let ((c (enclave-conn irc: 'sock config: (enclave-config)))+430
(far (+ (current-second) 60))+431
(past (- (current-second) 1)))+432
(enclave-conn-ping-add! c "apk-t" (current-second))+433
(assert-equal 'unconfirmed (confirm-verdict c "apk-t" 'sock past))+434
(assert-equal 'link-changed (confirm-verdict c "apk-t" 'other far))+435
(set-enclave-conn-shutdown?! c #t)+436
(assert-equal 'link-down (confirm-verdict c "apk-t" 'sock far))))+437
438
(test "an ANSWERED ping is evidence, and only for its own token" 439
;; The positive control for the test above: the same predicate 440
;; must report #t when the peer really did answer, or "not acked"