================================================================================================ PROPOSAL - [MINOR] functional - WebClientProtocol.sendLock Field javadoc still documents the partial-frame contract the rewrite removed ================================================================================================ REVIEW FINDING (abridged) "The field javadoc still documents the removed contract [...] Every clause after 'Both' is now false: after the MSG_CHUNK rewrite there are no partial frames, and sendBinaryMessageStreamed does not acquire sendLock [...] PushMessagesWorker's copy of this javadoc was updated by the same diff; this one was missed." FILES src/com/goldencode/p2j/ui/client/driver/web/WebClientProtocol.java ------------------------------------------------------------------------------------------------ 1. ROOT CAUSE ------------------------------------------------------------------------------------------------ Current text, WebClientProtocol.java:385-391: /** * Gate serializing every actual websocket send. Both the {@link PushMessagesWorker}'s * whole-message sends and {@link #sendBinaryMessageStreamed} (which emits many partial frames for * one logical message) acquire this, so a streamed frame sequence is never interleaved with * another send on the same socket (which would corrupt the message and can raise * {@code WritePendingException}). */ private final Object sendLock = new Object(); Three claims, all now false: - sendBinaryMessageStreamed does not acquire sendLock. It queues whole messages via queueChunk (:1003), which takes lock, not sendLock. - There are no partial frames. sendPartial was deleted; the rewrite sends ordinary messages. - There is no "streamed frame sequence" to protect from interleaving. Interleaving is now the explicit goal - sendBinaryMessageStreamed's own javadoc (:929-931) says the heartbeat and other output "interleave freely between pieces", i.e. the exact opposite of what the field doc promises. sendLock occurs at three places in the file: this declaration, sendBinaryMessageSync (:1090), and the PushMessagesWorker constructor argument (:1966). Those two are the real holders. The same javadoc on PushMessagesWorker.sendLock (:138) was rewritten by this diff to the accurate wording; only this copy was missed. That asymmetry is what makes it worth fixing rather than tolerating - two fields named sendLock now document contradictory contracts. ------------------------------------------------------------------------------------------------ 2. PROPOSED FIX ------------------------------------------------------------------------------------------------ Replace with a description of the contract that actually holds: /** * Gate serializing every actual websocket send. Held by {@link PushMessagesWorker} around each * whole-message send and by {@link #sendBinaryMessageSync}, so two sends never overlap on the * same socket (which would corrupt the message and can raise {@code WritePendingException}). *

* It is only ever held across a single whole message. Large payloads travel as a series of * ordinary {@link #MSG_CHUNK} messages queued by {@link #sendBinaryMessageStreamed}, which does * not take this lock, so nothing occupies the socket for a whole transfer and the keep-alive * heartbeat can always get a frame out between pieces. */ private final Object sendLock = new Object(); This mirrors the wording already applied to PushMessagesWorker.sendLock, so the two fields now read consistently, and it states the non-obvious part - that streamed sends deliberately do *not* hold it - which is the fact a maintainer is most likely to get wrong. Leave the file history block alone. Entry 045 already covers the MSG_CHUNK rewrite in this revision, and if this correction lands in the same commit it needs no separate entry; the historical PushMessagesWorker entry 009 ("Serialize all sends on a shared sendLock (so streamed partial-frame sends cannot interleave)") is a record of what was done then and is correctly left untouched. ------------------------------------------------------------------------------------------------ 3. RELATIONSHIP TO OTHER PROPOSALS ------------------------------------------------------------------------------------------------ None functionally. If proposal-issue-minor-performance-1 is taken, it changes how sendBinaryMessageStreamed throttles but not whether it takes sendLock, so this wording stays correct either way. ------------------------------------------------------------------------------------------------ 4. RISK AND VERIFICATION ------------------------------------------------------------------------------------------------ Risk: none. Comment-only. Verification 1. ./gradlew compile - the {@link #MSG_CHUNK} and {@link #sendBinaryMessageSync} references must resolve (MSG_CHUNK is inherited from WebClientMessageTypes, so #MSG_CHUNK is valid here; use {@link WebClientMessageTypes#MSG_CHUNK} if javadoc warns). 2. ./gradlew javadoc produces no new warnings for this file. 3. Read the two sendLock javadocs side by side and confirm they now describe the same contract.