# 넘침 분기 전체
  GrpcSerializedStreamWriter.java:70     if (!state.acceptsMessages()) {
  GrpcSerializedStreamWriter.java:71       return GrpcStreamWriteResult.REJECTED_CLOSED;
  GrpcSerializedStreamWriter.java:72     }
  GrpcSerializedStreamWriter.java:73     long nextBytes = payloadSizer.getAsLong();
  GrpcSerializedStreamWriter.java:74     GrpcFlowControlDecision decision =
  GrpcSerializedStreamWriter.java:75         flowControl.decide(queue.size(), queuedBytes, nextBytes, transportReady);
  GrpcSerializedStreamWriter.java:76     return switch (decision.action()) {
  GrpcSerializedStreamWriter.java:77       case TERMINATE -> {
  GrpcSerializedStreamWriter.java:78         state = GrpcStreamWriterState.DRAINING;
  GrpcSerializedStreamWriter.java:79         yield GrpcStreamWriteResult.OVERFLOW_TERMINATING;
  GrpcSerializedStreamWriter.java:80       }
  GrpcSerializedStreamWriter.java:81       case DROP_OLDEST -> {
  GrpcSerializedStreamWriter.java:82         GrpcStreamEnvelope<T> dropped = queue.pollFirst();
  GrpcSerializedStreamWriter.java:83         if (dropped != null) {
  GrpcSerializedStreamWriter.java:84           queuedBytes = Math.max(0L, queuedBytes - nextBytes);
  GrpcSerializedStreamWriter.java:85           droppedMessages++;
  GrpcSerializedStreamWriter.java:86         }
  GrpcSerializedStreamWriter.java:87         enqueue(kind, payload, snapshotVersion, resumeToken, nextBytes);
  GrpcSerializedStreamWriter.java:88         yield GrpcStreamWriteResult.DROPPED;
  GrpcSerializedStreamWriter.java:89       }
  GrpcSerializedStreamWriter.java:90       case PAUSE, PROCEED -> {
  GrpcSerializedStreamWriter.java:91         enqueue(kind, payload, snapshotVersion, resumeToken, nextBytes);
  GrpcSerializedStreamWriter.java:92         yield GrpcStreamWriteResult.ACCEPTED;
  GrpcSerializedStreamWriter.java:93       }
  GrpcSerializedStreamWriter.java:94     };
  GrpcSerializedStreamWriter.java:95   }
  GrpcSerializedStreamWriter.java:96 
  GrpcSerializedStreamWriter.java:97   private void enqueue(
  크기를 어디서 얻는가 :
  GrpcSerializedStreamWriter.java:30  private final LongSupplier payloadSizer;
  GrpcSerializedStreamWriter.java:41  * @param payloadSizer the serialized size of the next payload, for the byte bound
  GrpcSerializedStreamWriter.java:48  LongSupplier payloadSizer) {
  GrpcSerializedStreamWriter.java:53  || payloadSizer == null) {
  GrpcSerializedStreamWriter.java:60  this.payloadSizer = payloadSizer;
  GrpcSerializedStreamWriter.java:73  long nextBytes = payloadSizer.getAsLong();

# 봉투가 담는 것
  GrpcStreamEnvelope.java:16 public record GrpcStreamEnvelope<T>(
  GrpcStreamEnvelope.java:17     GrpcStreamId streamId,
  GrpcStreamEnvelope.java:18     long sequence,
  GrpcStreamEnvelope.java:19     Kind kind,
  GrpcStreamEnvelope.java:20     Optional<String> snapshotVersion,
  GrpcStreamEnvelope.java:21     Optional<String> resumeToken,
  GrpcStreamEnvelope.java:22     Optional<GrpcStreamTerminationReason> terminationReason,
  GrpcStreamEnvelope.java:23     Optional<T> payload) {
  GrpcStreamEnvelope.java:24 
  GrpcStreamEnvelope.java:25   /** What a stream message is. */

# 누적 바이트가 무엇에 쓰이는가 — decide 의 분기 전부
  GrpcFlowControlPolicy.java:56     boolean overflowsCount = queuedMessages >= maxQueuedMessages;
  GrpcFlowControlPolicy.java:57     boolean overflowsBytes = queuedBytes + nextMessageBytes > maxQueuedBytes;
  GrpcFlowControlPolicy.java:58     if (overflowsCount || overflowsBytes) {
  GrpcFlowControlPolicy.java:59       return switch (slowConsumerPolicy) {
  GrpcFlowControlPolicy.java:60         case TERMINATE ->
  GrpcFlowControlPolicy.java:61             new GrpcFlowControlDecision(
  GrpcFlowControlPolicy.java:62                 GrpcFlowControlDecision.Action.TERMINATE,
  GrpcFlowControlPolicy.java:63                 queuedMessages,
  GrpcFlowControlPolicy.java:64                 queuedBytes,
  GrpcFlowControlPolicy.java:65                 overflowsCount
  GrpcFlowControlPolicy.java:66                     ? "queue is at its " + maxQueuedMessages + "-message bound"
  GrpcFlowControlPolicy.java:67                     : "queue would exceed its " + maxQueuedBytes + "-byte bound");
  GrpcFlowControlPolicy.java:68         case DROP_OLDEST ->
  GrpcFlowControlPolicy.java:69             new GrpcFlowControlDecision(
  GrpcFlowControlPolicy.java:70                 GrpcFlowControlDecision.Action.DROP_OLDEST,
  GrpcFlowControlPolicy.java:71                 queuedMessages,
  GrpcFlowControlPolicy.java:72                 queuedBytes,
  GrpcFlowControlPolicy.java:73                 "the profile permits loss; dropping the oldest queued message");
  GrpcFlowControlPolicy.java:74       };
  GrpcFlowControlPolicy.java:75     }
  GrpcFlowControlPolicy.java:76     if (!transportReady || queuedMessages >= highWaterMarkMessages) {
  GrpcFlowControlPolicy.java:77       return new GrpcFlowControlDecision(
  GrpcFlowControlPolicy.java:78           GrpcFlowControlDecision.Action.PAUSE,
  GrpcFlowControlPolicy.java:79           queuedMessages,
  GrpcFlowControlPolicy.java:80           queuedBytes,
  GrpcFlowControlPolicy.java:81           transportReady
  GrpcFlowControlPolicy.java:82               ? "queue reached its high-water mark of " + highWaterMarkMessages
  GrpcFlowControlPolicy.java:83               : "the transport is not ready for more");
  GrpcFlowControlPolicy.java:84     }
  GrpcFlowControlPolicy.java:85     return new GrpcFlowControlDecision(
  GrpcFlowControlPolicy.java:86         GrpcFlowControlDecision.Action.PROCEED, queuedMessages, queuedBytes, "within bounds");
  GrpcFlowControlPolicy.java:87   }
  바이트 경계를 두는 이유 :
  GrpcFlowControlPolicy.java:6  * <p>Both a message count and a byte count, because either alone is unbounded in the other
  GrpcFlowControlPolicy.java:7  * dimension: a thousand-message bound with no byte bound is a memory limit set by the largest
  GrpcFlowControlPolicy.java:8  * message anyone ever sends, and a byte bound with no count bound is unbounded queue overhead.

# 이 타입을 참조하는 자리 — 경로 제한 없이 저장소 전체
  $ git grep -n GrpcSerializedStreamWriter   (pathspec 없음)
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3679:- Create: `modules/grpc/grpc-policy/src/main/jav
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3682:- Test: `modules/grpc/grpc-policy/src/test/java/
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3698:class GrpcSerializedStreamWriterTest {
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3701:        var writer = GrpcSerializedStreamWriter.
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3716:./gradlew :modules:grpc:grpc-policy:test --tests
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3728:public final class GrpcSerializedStreamWriter<T>
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3731:    private GrpcSerializedStreamWriter(int capac
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3736:    public static <T> GrpcSerializedStreamWriter
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3738:        return new GrpcSerializedStreamWriter<>(
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3763:./gradlew :modules:grpc:grpc-policy:test --tests
docs/2026-08-13-grpc-type-safe-rpc-platform-implementation-plan.md:3772:git add 'modules/grpc/grpc-policy/src/main/java/
docs/adr/ADR-GRPC-005-server-streaming-single-writer-and-resume.md:20:**A bounded queue drained by one writer.** `GrpcSe
  main · GrpcSerializedStreamWriter.java:24 public final class GrpcSerializedStreamWriter<T> {
  main · GrpcSerializedStreamWriter.java:43   public GrpcSerializedStreamWriter(
  test · GrpcSerializedStreamWriterTest.java:15 class GrpcSerializedStreamWriterTest {
  test · GrpcSerializedStreamWriterTest.java:22   private GrpcSerializedStreamWriter<String> writer(
  test · GrpcSerializedStreamWriterTest.java:24     return new GrpcSerializedStreamWriter<>(
  test · GrpcSerializedStreamWriterTest.java:31     GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControlP
  test · GrpcSerializedStreamWriterTest.java:47     GrpcSerializedStreamWriter<String> writer =
  test · GrpcSerializedStreamWriterTest.java:87     GrpcSerializedStreamWriter<String> writer =
  test · GrpcSerializedStreamWriterTest.java:103     GrpcSerializedStreamWriter<String> writer =
  test · GrpcSerializedStreamWriterTest.java:116     GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControl
  test · GrpcSerializedStreamWriterTest.java:129     GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControl
  자기 파일 밖 main 참조 : 0 개 파일

# 대응 시험이 크기 공급자에 주는 값
  GrpcSerializedStreamWriterTest.java:22   private GrpcSerializedStreamWriter<String> writer(
  GrpcSerializedStreamWriterTest.java:23       GrpcFlowControlPolicy policy, long messageSize) {
  GrpcSerializedStreamWriterTest.java:24     return new GrpcSerializedStreamWriter<>(
  GrpcSerializedStreamWriterTest.java:25         STREAM, GrpcStreamSequence.forNewStream(STREAM), policy, sent::add, () -> messageSize);
  GrpcSerializedStreamWriterTest.java:26   }
  GrpcSerializedStreamWriterTest.java:31  GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControlPolicy.stable(), 16L);
  GrpcSerializedStreamWriterTest.java:49  new GrpcFlowControlPolicy(1000, 1_000_000L, 999, GrpcSlowConsumerPolicy.TERMINATE), 1L);
  GrpcSerializedStreamWriterTest.java:88  writer(new GrpcFlowControlPolicy(1, 1024L, 1, GrpcSlowConsumerPolicy.TERMINATE), 8L);
  GrpcSerializedStreamWriterTest.java:104  writer(new GrpcFlowControlPolicy(1, 1024L, 1, GrpcSlowConsumerPolicy.DROP_OLDEST), 8L);
  GrpcSerializedStreamWriterTest.java:116  GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControlPolicy.stable(), 8L);
  GrpcSerializedStreamWriterTest.java:129  GrpcSerializedStreamWriter<String> writer = writer(GrpcFlowControlPolicy.stable(), 8L);
  DROP_OLDEST 를 쓰는 시험이 단언하는 것 :
  GrpcSerializedStreamWriterTest.java:101   @DisplayName("a lossy profile drops the oldest and reports it rather than hiding it")
  GrpcSerializedStreamWriterTest.java:102   void aLossyProfileReportsWhatItDropped() {
  GrpcSerializedStreamWriterTest.java:103     GrpcSerializedStreamWriter<String> writer =
  GrpcSerializedStreamWriterTest.java:104         writer(new GrpcFlowControlPolicy(1, 1024L, 1, GrpcSlowConsumerPolicy.DROP_OLDEST), 8L);
  GrpcSerializedStreamWriterTest.java:105     writer.write(GrpcStreamEnvelope.Kind.LIVE, "first", null, null, true);
  GrpcSerializedStreamWriterTest.java:106 
  GrpcSerializedStreamWriterTest.java:107     assertThat(writer.write(GrpcStreamEnvelope.Kind.LIVE, "second", null, null, true))
  GrpcSerializedStreamWriterTest.java:108         .isEqualTo(GrpcStreamWriteResult.DROPPED);
  GrpcSerializedStreamWriterTest.java:109     assertThat(writer.droppedMessages()).isEqualTo(1);
  GrpcSerializedStreamWriterTest.java:110     assertThat(writer.queuedMessages()).isEqualTo(1);
  GrpcSerializedStreamWriterTest.java:111   }
  GrpcSerializedStreamWriterTest.java:112 

# 프로브 — 두 방향과 TERMINATE 가능성
# 실제 큐는 writer 의 queue 필드를 읽어 봉투마다 원래 크기를 되찾아 합산한다

  가. 작은 것을 버리며 큰 것을 넣는다 — 과소 계상
    정책 : 메시지 상한 3 · 바이트 상한 1000000 · DROP_OLDEST
    n   insize   result      writerBytes    realQueue        err
    1   100       ACCEPTED            100          100          0
    2   100       ACCEPTED            200          200          0
    3   100       ACCEPTED            300          300          0
    4   1000      DROPPED            1000         1200       -200
    5   1000      DROPPED            1000         2100      -1100
    6   1000      DROPPED            1000         3000      -2000
    7   1000      DROPPED            1000         3000      -2000
    8   1000      DROPPED            1000         3000      -2000
    9   1000      DROPPED            1000         3000      -2000
    남은 메시지 3 · 버린 수 6 · 상태 OPEN

  나. 큰 것을 버리며 작은 것을 넣는다 — 과대 계상
    정책 : 메시지 상한 3 · 바이트 상한 25000 · DROP_OLDEST
    n   insize   result      writerBytes    realQueue        err
    1   10000     ACCEPTED          10000        10000          0
    2   10000     ACCEPTED          20000        20000          0
    3   10        ACCEPTED          20010        20010          0
    4   10        DROPPED           20010        10020       9990
    5   10        DROPPED           20010           30      19980
    6   10        DROPPED           20010           30      19980
    7   5000      DROPPED           20010         5020      14990
    8   10        DROPPED           20010         5020      14990
    9   10        DROPPED           20010         5020      14990
    남은 메시지 3 · 버린 수 6 · 상태 OPEN

# DROP_OLDEST 를 쓰는 writer 가 TERMINATE 결정을 받을 수 있는가
    decide 를 156282 조합으로 불렀을 때 TERMINATE 가 나온 횟수 : 0
    그 정책 값으로 낼 수 있는 결정 : [DROP_OLDEST, PAUSE, PROCEED]
