Commit d8ffd35
test: drive a real StreamConstraintsException through a real stream end to end
You were right to push on this, and my earlier wording was wrong. I said
the Exception arm "has always handled the literal incident" -- I meant
since the first commit OF THIS PR, which introduced the wrapper. Pre-PR
there was no try/catch in the codec at all, so the StreamConstraintsException
propagated up through CommandDecoder exactly as the original OPIK-8164
analysis said. Nothing of ours caught it.
And the drop mechanism was not actually tested for a real decode failure.
Every existing test either injected a pre-built UndecodableStreamMessage
into a mocked readGroup, or exercised the decoder in isolation. None
reproduced the thing that happened: written successfully, then failing on
the way back out below the subscriber.
New BaseRedisSubscriberTest.UndecodablePayloadTests does that on real
Redis -- a JAVA-shaped codec with a 512-byte string limit standing in for
production's 100 MB, so the write/read asymmetry reproduces at a few
hundred bytes. It asserts the entry writes fine, the healthy entry behind
it still processes, the undecodable one is NOT removed on first delivery,
and that it does leave once the delivery count reaches maxRetries.
Mutation-checked, and the mutant is the incident: making tolerant() a
no-op produces
io.netty.handler.codec.DecoderException:
com.fasterxml.jackson.core.exc.StreamConstraintsException:
String value length (513) exceeds the maximum allowed (512, ...)
which is the production stack trace's exact shape, and the test fails at
the FIRST await -- the healthy entry behind it never processes either.
That is the batch-stranding half of the wedge, now covered.
Two things the run exposed, both documented in the test:
- Retirement is driven by the delivery count, which only advances when
XAUTOCLAIM redelivers after pendingMessageDuration. At the shipped
online-scoring values (10m, maxRetries 3) an undecodable entry sits in
the stream for ~30 minutes, re-read and re-decoded each cycle, before
removal. Bounded, not eliminated -- and at production payload sizes each
cycle re-attempts a large materialization. The test compresses the
timers to 500ms/2 to stay fast.
- My first attempt at this test published before subscriber.start(), so
the consumer group was created at '$' and never saw the entries. That
was a test bug, not a code one, but it is why the ordering is now
explicit with a comment.
RedisStreamCodec.faultTolerant widens from package-private to public
@VisibleForTesting so the subscriber test package can build the codec.
59 green, 0 skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 7cef0b8 commit d8ffd35
2 files changed
Lines changed: 99 additions & 1 deletion
File tree
- apps/opik-backend/src
- main/java/com/comet/opik/infrastructure/redis
- test/java/com/comet/opik/api/resources/v1/events
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
66 | | - | |
| 66 | + | |
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| |||
Lines changed: 98 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| |||
22 | 24 | | |
23 | 25 | | |
24 | 26 | | |
| 27 | + | |
| 28 | + | |
25 | 29 | | |
| 30 | + | |
26 | 31 | | |
27 | 32 | | |
28 | 33 | | |
| |||
89 | 94 | | |
90 | 95 | | |
91 | 96 | | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
92 | 190 | | |
93 | 191 | | |
94 | 192 | | |
| |||
0 commit comments