c553d795d8
failPendingPublishesOnRecovery walked and cleared pendingBySeq/pendingByMsgId without holding publishChannelLock, so a publish() that registered while the sweep was still iterating could be failed even though it published on the already-recovered channel — a successful publish reported as failed, and since MessageService.reply mints a fresh msgId per retry, dedup can't catch the resulting duplicate. Guard the sweep with publishChannelLock: publish() only holds it for the seq/map-put/basicPublish, so the sweep can only ever wait for an in-flight basicPublish to return, never a broker round trip. Also make close() fail in-flight publishes immediately with a clear message instead of leaving them to idle out the 10s confirm timeout, and record the (currently unreachable) msgId-uniqueness assumption pendingByMsgId relies on. AmqpReplyInboxRecoveryRaceTest drives the sweep and a real publish() against each other directly (no live broker reconnect) using Proxy-backed fake AMQP channels and a large in-flight backlog to make the race window observable; confirmed it fails without the guard (reply "fresh" wrongly failed as "connection recovered mid-publish") and passes with it.