He-Pin commented on code in PR #3740:
URL: https://github.com/apache/pekko/pull/3740#discussion_r4430941678


##########
stream/src/main/scala/org/apache/pekko/stream/impl/io/TLSActor.scala:
##########
@@ -287,6 +289,12 @@ import pekko.util.ByteString
     }
   }
 
+  val signallingInboundTruncation = TransferPhase(userOutDemand) { () =>
+    if (tracing) log.debug("signalling SessionTruncated after TransportOut 
cancellation")
+    outputBunch.enqueue(UserOut, SessionTruncated)
+    nextPhase(completedPhase)
+  }

Review Comment:
   This does not apply to the actor engine. The guard is present, it is just 
expressed as the phase precondition instead of an `if`.
   
   `OutputBunch` keeps no per-output element buffer, so there is nothing to 
overwrite and no enqueue that can fail:
   
   - `OutputBunch.enqueue` (FanOut.scala) calls 
`outputs(id).enqueueOutputElement(elem)` and then refreshes `pending(id)` from 
`output.demandAvailable`;
   - `SimpleOutputs.enqueueOutputElement` (ActorProcessor.scala) is 
`downstreamDemand -= 1; tryOnNext(subscriber, elem)` — it emits immediately 
rather than parking an element;
   - `OutputBunch.demandAvailableFor(id)` (FanOut.scala) defines `isReady = 
pending(id)`, so `pending` mirrors downstream *demand*, not a buffered element.
   
   `signallingInboundTruncation = TransferPhase(userOutDemand)` therefore only 
runs while demand is available: `Pump.pump()` executes the action only while 
`transferState.isExecutable` (`isReady && !isCompleted`). If `flushToUser()` 
consumed the last unit of demand in the same round, `pending(UserOut)` goes 
false, the pump parks, and the report is emitted after the next 
`SubstreamRequestMore`. That is exactly the ordering the "buffered records 
outnumber the plaintext demand" case in `TlsTransportOutputCancelSpec` pins by 
granting one demand unit at a time.
   
   `TlsGraphStage` needs the explicit `!userOutput.hasPending` check because 
its `OutputSlot` really does hold one element and `enqueue` throws 
`IllegalStateException("TLS output slot already has pending data")` on a second 
one. The asymmetry is between the two engines' output slots, not a missing 
guard here.
   
   Worth noting in passing: `SubstreamCancel` sets `cancelled(id)` without 
clearing `pending(id)`, so `userOutDemand.isReady` can stay true after the 
plaintext output is cancelled — but `isCompleted` becomes true at the same 
time, so `isExecutable` is false and nothing is emitted. That is why the gate 
is on the whole `TransferState` rather than on demand alone.



##########
stream/src/main/scala/org/apache/pekko/stream/impl/io/TLSActor.scala:
##########
@@ -352,6 +361,21 @@ import pekko.util.ByteString
       }
     }
 
+  /**
+   * Closing the inbound side is what reveals whether the peer's close_notify 
is still missing, so
+   * the plaintext output can learn that inbound records buffered from here on 
are unreachable. The
+   * read side is cancelled first because delivering that report may have to 
wait for plaintext
+   * demand, and a subscribed transport input would overrun its buffer while 
the pump is parked.
+   */
+  private def inboundTruncationOwed(): Boolean =
+    if (!corkUser && !engine.isInboundDone && !userOutDemand.isCompleted) {
+      inputBunch.cancel()
+      try {
+        engine.closeInbound()
+        false
+      } catch { case _: SSLException => true }
+    } else false

Review Comment:
   Duplicate of the thread on line 296 — same answer: `OutputBunch` has no 
element buffer (`enqueueOutputElement` is `downstreamDemand -= 1; 
tryOnNext(...)`), `pending(id)` mirrors downstream demand, and 
`TransferPhase(userOutDemand)` is the guard, since `Pump.pump()` only runs the 
action while `isReady && !isCompleted`. The `!userOutput.hasPending` check in 
`TlsGraphStage` exists because that engine's `OutputSlot` buffers one element 
and throws on a second enqueue; the actor engine has no such slot.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to