@@ -148,46 +148,48 @@ func (bs *BufferedSender) sendBuffered(
148
148
// registration. This error should be the next event that is sent to
149
149
// stream.
150
150
//
151
- // NB: The zero-value of streamStatus is the valid state of a newly seen
152
- // stream.
153
- status := bs .queueMu .byStream [ev .StreamID ]
154
- switch status .state {
155
- case streamActive :
156
- if bs .queueMu .perStreamCapacity > 0 && status .queueItems == bs .queueMu .perStreamCapacity {
157
- if ev .Error != nil {
158
- // If _this_ event is an error, no use sending another error. This stream
159
- // is going down. Admit this error and mark the stream as overflowed.
160
- status .state = streamOverflowed
161
- } else {
162
- // This stream is at capacity, return an error to the registration that it
163
- // should send back to us after cleaning up.
164
- status .state = streamOverflowing
165
- return newRetryErrBufferCapacityExceeded ()
151
+ // NB: We don't error if the stream status is not found as this may be an
152
+ // event for an already closed stream. Such events are possible while the
153
+ // registration publishes the catch up scan buffer.
154
+ status , ok := bs .queueMu .byStream [ev .StreamID ]
155
+ if ok {
156
+ switch status .state {
157
+ case streamActive :
158
+ if bs .queueMu .perStreamCapacity > 0 && status .queueItems == bs .queueMu .perStreamCapacity {
159
+ if ev .Error != nil {
160
+ // If _this_ event is an error, no use sending another error. This stream
161
+ // is going down. Admit this error and mark the stream as overflowed.
162
+ status .state = streamOverflowed
163
+ } else {
164
+ // This stream is at capacity, return an error to the registration that it
165
+ // should send back to us after cleaning up.
166
+ status .state = streamOverflowing
167
+ return newRetryErrBufferCapacityExceeded ()
168
+ }
166
169
}
170
+ case streamOverflowing :
171
+ // The unbufferedRegistration is the only component that sends non-error
172
+ // events to our stream. In response to the error we return when moving to
173
+ // stateOverflowing, it should immediately send us an error and mark itself
174
+ // as disconnected. As a result, no non-error events are expected.
175
+ if ev .Error == nil {
176
+ panic ("only error events expected after stream has exceeded capacity" )
177
+ }
178
+ status .state = streamOverflowed
179
+ case streamOverflowed :
180
+ // If we are overflowed, we don't expect any further events because the
181
+ // registration should have disconnected in response to the error.
182
+ //
183
+ // TODO(ssd): Consider adding an assertion here.
184
+ return nil
185
+ default :
186
+ panic (fmt .Sprintf ("unhandled stream state: %v" , status .state ))
167
187
}
168
- case streamOverflowing :
169
- // The unbufferedRegistration is the only component that sends non-error
170
- // events to our stream. In response to the error we return when moving to
171
- // stateOverflowing, it should immediately send us an error and mark itself
172
- // as disconnected. As a result, no non-error events are expected.
173
- if ev .Error == nil {
174
- panic ("only error events expected after stream has exceeded capacity" )
175
- }
176
- status .state = streamOverflowed
177
- case streamOverflowed :
178
- // If we are overflowed, we don't expect any further events because the
179
- // registration should have disconnected in response to the error.
180
- //
181
- // TODO(ssd): Consider adding an assertion here.
182
- return nil
183
- default :
184
- panic (fmt .Sprintf ("unhandled stream state: %v" , status .state ))
188
+ // We are admitting this event.
189
+ status .queueItems ++
190
+ bs .queueMu .byStream [ev .StreamID ] = status
185
191
}
186
192
187
- // We are admitting this event.
188
- status .queueItems ++
189
- bs .queueMu .byStream [ev .StreamID ] = status
190
-
191
193
// TODO(wenyihu6): pass an actual context here
192
194
alloc .Use (context .Background ())
193
195
bs .queueMu .buffer .pushBack (sharedMuxEvent {ev , alloc })
@@ -260,6 +262,14 @@ func (bs *BufferedSender) popFront() (e sharedMuxEvent, success bool) {
260
262
return event , ok
261
263
}
262
264
265
+ func (bs * BufferedSender ) addStream (streamID int64 ) {
266
+ bs .queueMu .Lock ()
267
+ defer bs .queueMu .Unlock ()
268
+ if _ , ok := bs .queueMu .byStream [streamID ]; ! ok {
269
+ bs .queueMu .byStream [streamID ] = streamStatus {}
270
+ }
271
+ }
272
+
263
273
func (bs * BufferedSender ) removeStream (streamID int64 ) {
264
274
bs .queueMu .Lock ()
265
275
defer bs .queueMu .Unlock ()
0 commit comments