|
1
|
================================================================================================
|
|
2
|
PROPOSAL - [MINOR] functional - PushMessagesWorker.getQueueSize
|
|
3
|
Dead method whose javadoc documents a guard that was never built
|
|
4
|
================================================================================================
|
|
5
|
|
|
6
|
REVIEW FINDING (abridged)
|
|
7
|
"Newly added by this change with no caller anywhere in the tree [...] yet its javadoc asserts a
|
|
8
|
use that does not exist: 'Used by the keep-alive timer to tell its own silence apart from a
|
|
9
|
backlog' [...] The claim is not merely unimplemented but unimplementable as written."
|
|
10
|
|
|
11
|
FILES
|
|
12
|
src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java
|
|
13
|
|
|
14
|
------------------------------------------------------------------------------------------------
|
|
15
|
1. ROOT CAUSE
|
|
16
|
------------------------------------------------------------------------------------------------
|
|
17
|
|
|
18
|
The method (PushMessagesWorker.java:398-409) is added by this revision and has no caller anywhere -
|
|
19
|
grep across src/, test/ and tools/ finds only the declaration. Its javadoc nevertheless says:
|
|
20
|
|
|
21
|
* Used by the keep-alive timer to tell its own silence apart from a backlog: while output is
|
|
22
|
* queued the peer may simply not have been asked anything yet, so its silence proves nothing.
|
|
23
|
|
|
24
|
WebClientProtocol.startKeepAlivePing's TimerTask reads pushWorker only to call pushMessageFirst and
|
|
25
|
decides peer death purely from dataQuietMs >= dataIdleMs - tickMs. There is no backlog term.
|
|
26
|
|
|
27
|
The claim is not just unimplemented, it is unimplementable in this form, for two independent
|
|
28
|
reasons:
|
|
29
|
|
|
30
|
(a) The premise is already false. pushMessageFirst (:280) enqueues the heartbeat with offerFirst
|
|
31
|
and bypasses awaitCapacity entirely, so a deep queue cannot delay the ping behind it. The
|
|
32
|
backlog the javadoc worries about does not in fact keep the peer from being asked.
|
|
33
|
|
|
34
|
(b) The measurement would not see the case that matters. sendMessage polls the message off the
|
|
35
|
deque *before* the blocking write, so during the only scenario that can genuinely starve the
|
|
36
|
heartbeat - a stalled send, where the peer has stopped draining its socket - getQueueSize()
|
|
37
|
reads 0. The proposed guard would be blind precisely when it was needed.
|
|
38
|
|
|
39
|
Separately, ConcurrentLinkedDeque.size() is a documented O(n) traversal, so it would be the wrong
|
|
40
|
primitive for a per-tick check even if a depth check were wanted.
|
|
41
|
|
|
42
|
Leaving this in place is a maintenance hazard rather than a runtime one: the next person to read
|
|
43
|
startKeepAlivePing will believe a backlog guard exists somewhere and reason about the heartbeat on
|
|
44
|
that basis.
|
|
45
|
|
|
46
|
------------------------------------------------------------------------------------------------
|
|
47
|
2. PROPOSED FIX
|
|
48
|
------------------------------------------------------------------------------------------------
|
|
49
|
|
|
50
|
2.1 Delete the method
|
|
51
|
-----------------------
|
|
52
|
|
|
53
|
- /**
|
|
54
|
- * The number of messages still waiting to be transmitted.
|
|
55
|
- * <p>
|
|
56
|
- * Used by the keep-alive timer to tell its own silence apart from a backlog: while output is
|
|
57
|
- * queued the peer may simply not have been asked anything yet, so its silence proves nothing.
|
|
58
|
- *
|
|
59
|
- * @return The current depth of the outbound queue.
|
|
60
|
- */
|
|
61
|
- public int getQueueSize()
|
|
62
|
- {
|
|
63
|
- return messages.size();
|
|
64
|
- }
|
|
65
|
|
|
66
|
Nothing else changes; there are no callers to update. The class already exposes queue pressure where
|
|
67
|
it is genuinely needed, through awaitCapacity/queuedBytes, which is byte-based and O(1).
|
|
68
|
|
|
69
|
2.2 Record why, where the next reader will look
|
|
70
|
-------------------------------------------------
|
|
71
|
|
|
72
|
The reasoning above is worth keeping, but it belongs next to the decision it explains, not on a
|
|
73
|
deleted method. Add it to startKeepAlivePing's javadoc in WebClientProtocol, which already documents
|
|
74
|
the deadline design:
|
|
75
|
|
|
76
|
+ * <p>
|
|
77
|
+ * The deadline deliberately does not consider the outbound queue depth. A backlog cannot delay
|
|
78
|
+ * the heartbeat - {@link PushMessagesWorker#pushMessageFirst} enqueues it at the head and skips
|
|
79
|
+ * the backpressure gate - and the one condition that can starve it, a send stalled on a peer
|
|
80
|
+ * that has stopped reading, leaves the queue reading empty because the message has already been
|
|
81
|
+ * polled off it. A peer that has not accepted a byte for a whole deadline is correctly closed.
|
|
82
|
|
|
83
|
2.3 If a backlog guard is actually wanted
|
|
84
|
-------------------------------------------
|
|
85
|
|
|
86
|
It should not be built on queue depth. The measurable signal is *completed writes*: a monotonic
|
|
87
|
counter incremented in sendMessage after a successful send would distinguish "the socket is still
|
|
88
|
draining, the page is just behind" from "nothing is moving at all", and unlike queue depth it is not
|
|
89
|
blind to the in-flight message. That is a design change to the deadline, not a javadoc fix, and
|
|
90
|
should be raised as its own task with a stated failure case; it is out of scope here.
|
|
91
|
|
|
92
|
------------------------------------------------------------------------------------------------
|
|
93
|
3. RELATIONSHIP TO OTHER PROPOSALS
|
|
94
|
------------------------------------------------------------------------------------------------
|
|
95
|
|
|
96
|
None. This is self-contained.
|
|
97
|
|
|
98
|
Note for the history block: the method was added under entry 010 in this same revision, so removing
|
|
99
|
it needs no new history entry if the change is folded into the same commit; if it lands separately,
|
|
100
|
add one rather than editing 010.
|
|
101
|
|
|
102
|
------------------------------------------------------------------------------------------------
|
|
103
|
4. RISK AND VERIFICATION
|
|
104
|
------------------------------------------------------------------------------------------------
|
|
105
|
|
|
106
|
Risk: none. The method is unreferenced.
|
|
107
|
|
|
108
|
Verification
|
|
109
|
1. grep -rn "getQueueSize" src/ test/ tools/ returns nothing after the change.
|
|
110
|
2. ./gradlew compile succeeds.
|
|
111
|
3. Confirm no rules/ TRPL or reflection-based lookup names the method (grep the whole tree, not
|
|
112
|
just the Java source) - it is a public method on a public class, so this is worth one check
|
|
113
|
even though no such usage is plausible.
|