@@ -153,10 +153,9 @@ func scanEvents(r io.Reader) iter.Seq2[Event, error] {
153
153
//
154
154
// All of an EventStore's methods must be safe for use by multiple goroutines.
155
155
type EventStore interface {
156
- // AppendEvent appends data for an outgoing event to given stream, which is part of the
157
- // given session. It returns the index of the event in the stream, suitable for constructing
158
- // an event ID to send to the client.
159
- AppendEvent (_ context.Context , sessionID string , _ StreamID , data []byte ) (int , error )
156
+ // Append appends data for an outgoing event to given stream, which is part of the
157
+ // given session.
158
+ Append (_ context.Context , sessionID string , _ StreamID , data []byte ) error
160
159
161
160
// After returns an iterator over the data for the given session and stream, beginning
162
161
// just after the given index.
@@ -165,16 +164,15 @@ type EventStore interface {
165
164
// dropped; it must not return partial results.
166
165
After (_ context.Context , sessionID string , _ StreamID , index int ) iter.Seq2 [[]byte , error ]
167
166
168
- // StreamClosed informs the store that the given stream is finished.
169
- // A store cannot rely on this method being called for cleanup. It should institute
170
- // additional mechanisms, such as timeouts, to reclaim storage.
171
- StreamClosed (_ context.Context , sessionID string , streamID StreamID ) error
172
-
173
167
// SessionClosed informs the store that the given session is finished, along
174
168
// with all of its streams.
175
169
// A store cannot rely on this method being called for cleanup. It should institute
176
170
// additional mechanisms, such as timeouts, to reclaim storage.
171
+ //
177
172
SessionClosed (_ context.Context , sessionID string ) error
173
+
174
+ // There is no StreamClosed method. A server doesn't know when a stream is finished, because
175
+ // the client can always send a GET with a Last-Event-ID referring to the stream.
178
176
}
179
177
180
178
// A dataList is a list of []byte.
@@ -210,15 +208,6 @@ func (dl *dataList) removeFirst() int {
210
208
return r
211
209
}
212
210
213
- // lastIndex returns the index of the last data item in dl.
214
- // It panics if there are none.
215
- func (dl * dataList ) lastIndex () int {
216
- if len (dl .data ) == 0 {
217
- panic ("empty dataList" )
218
- }
219
- return dl .first + len (dl .data ) - 1
220
- }
221
-
222
211
// A MemoryEventStore is an [EventStore] backed by memory.
223
212
type MemoryEventStore struct {
224
213
mu sync.Mutex
@@ -267,9 +256,8 @@ func NewMemoryEventStore(opts *MemoryEventStoreOptions) *MemoryEventStore {
267
256
}
268
257
}
269
258
270
- // AppendEvent implements [EventStore.AppendEvent] by recording data
271
- // in memory.
272
- func (s * MemoryEventStore ) AppendEvent (_ context.Context , sessionID string , streamID StreamID , data []byte ) (int , error ) {
259
+ // Append implements [EventStore.Append] by recording data in memory.
260
+ func (s * MemoryEventStore ) Append (_ context.Context , sessionID string , streamID StreamID , data []byte ) error {
273
261
s .mu .Lock ()
274
262
defer s .mu .Unlock ()
275
263
@@ -288,9 +276,13 @@ func (s *MemoryEventStore) AppendEvent(_ context.Context, sessionID string, stre
288
276
s .purge ()
289
277
dl .appendData (data )
290
278
s .nBytes += len (data )
291
- return dl . lastIndex (), nil
279
+ return nil
292
280
}
293
281
282
+ // ErrEventsPurged is the error that [EventStore.After] should return if the event just after the
283
+ // index is no longer available.
284
+ var ErrEventsPurged = errors .New ("data purged" )
285
+
294
286
// After implements [EventStore.After].
295
287
func (s * MemoryEventStore ) After (_ context.Context , sessionID string , streamID StreamID , index int ) iter.Seq2 [[]byte , error ] {
296
288
// Return the data items to yield.
@@ -306,10 +298,12 @@ func (s *MemoryEventStore) After(_ context.Context, sessionID string, streamID S
306
298
if ! ok {
307
299
return nil , fmt .Errorf ("MemoryEventStore.After: unknown stream ID %v in session %q" , streamID , sessionID )
308
300
}
309
- if dl .first > index {
310
- return nil , fmt .Errorf ("MemoryEventStore.After: data purged at index %d, stream ID %v, session %q" , index , streamID , sessionID )
301
+ start := index + 1
302
+ if dl .first > start {
303
+ return nil , fmt .Errorf ("MemoryEventStore.After: index %d, stream ID %v, session %q: %w" ,
304
+ index , streamID , sessionID , ErrEventsPurged )
311
305
}
312
- return slices .Clone (dl .data [index - dl .first :]), nil
306
+ return slices .Clone (dl .data [start - dl .first :]), nil
313
307
}
314
308
315
309
return func (yield func ([]byte , error ) bool ) {
@@ -326,26 +320,6 @@ func (s *MemoryEventStore) After(_ context.Context, sessionID string, streamID S
326
320
}
327
321
}
328
322
329
- // StreamClosed implements [EventStore.StreamClosed].
330
- func (s * MemoryEventStore ) StreamClosed (_ context.Context , sessionID string , streamID StreamID ) error {
331
- if sessionID == "" {
332
- panic ("empty sessionID" )
333
- }
334
-
335
- s .mu .Lock ()
336
- defer s .mu .Unlock ()
337
-
338
- sm := s .store [sessionID ]
339
- dl := sm [streamID ]
340
- s .nBytes -= dl .size
341
- delete (sm , streamID )
342
- if len (sm ) == 0 {
343
- delete (s .store , sessionID )
344
- }
345
- s .validate ()
346
- return nil
347
- }
348
-
349
323
// SessionClosed implements [EventStore.SessionClosed].
350
324
func (s * MemoryEventStore ) SessionClosed (_ context.Context , sessionID string ) error {
351
325
s .mu .Lock ()
0 commit comments