The echo peer outlives a failed call instead of exiting

Peer's autoreply loop had no catch, so one failed poll or send to the relay
ended the process. The on-device reply case then waited out its 90 seconds
for an echo from a peer that was gone, which fits the one missed echo seen
in five full runs on 2026-09-28 (its log was lost, so not proven).

Each poll and each echo is now caught, logged to stderr with a timestamp
("poll failed, still answering: ..."), and the loop carries on. The
closing JSON adds an `errors` count. instrumented.sh already prints the
echo peer's log when a run fails, so a recurrence will say why.

Checked against a relay address that refuses connections: the old peer
exits 1 on the first poll with no result; the new one runs its full 8 s,
logs 4 failed polls and prints {"echoed":0,"errors":4}. Against relay1: 0
errors. Full on-device suite with the new peer: 10 of 10.

Harness only: interop/ is not shipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-09-28 10:11:30 -04:00
co-authored by Claude Opus 5.5
parent fdee288111
commit df56cf2e6e
@@ -120,15 +120,40 @@ object Peer {
val seconds = args.getOrNull(2)?.toIntOrNull() ?: 60
val deadline = System.currentTimeMillis() + seconds * 1000L
var replied = 0
var errors = 0
// One failed call is logged and outlived, not fatal. This loop
// used to have no catch at all, so a single dropped poll or send
// to the relay ended the process, and the on-device reply case
// waited out its 90 seconds for an echo from a peer that was no
// longer running. The log line is what the script prints when
// that case fails.
fun failed(
what: String,
e: Exception,
) {
errors += 1
System.err.println("${java.time.Instant.now()} $what failed, still answering: $e")
}
while (System.currentTimeMillis() < deadline) {
for (message in conversations.poll()) {
conversations.send(message.fromUser, "echo: " + message.text)
replied += 1
System.err.println("echoed to ${message.fromUser}: ${message.text}")
val received =
try {
conversations.poll()
} catch (e: Exception) {
failed("poll", e)
emptyList()
}
for (message in received) {
try {
conversations.send(message.fromUser, "echo: " + message.text)
replied += 1
System.err.println("echoed to ${message.fromUser}: ${message.text}")
} catch (e: Exception) {
failed("echo to ${message.fromUser}", e)
}
}
Thread.sleep(2000)
}
println(JSONObject().put("echoed", replied))
println(JSONObject().put("echoed", replied).put("errors", errors))
}
else -> {