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 like
test/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"