@@ -153,10 +153,9 @@ func scanEvents(r io.Reader) iter.Seq2[Event, error] {
153153//
154154// All of an EventStore's methods must be safe for use by multiple goroutines.
155155type 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
160159
161160 // After returns an iterator over the data for the given session and stream, beginning
162161 // just after the given index.
@@ -165,16 +164,15 @@ type EventStore interface {
165164 // dropped; it must not return partial results.
166165 After (_ context.Context , sessionID string , _ StreamID , index int ) iter.Seq2 [[]byte , error ]
167166
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-
173167 // SessionClosed informs the store that the given session is finished, along
174168 // with all of its streams.
175169 // A store cannot rely on this method being called for cleanup. It should institute
176170 // additional mechanisms, such as timeouts, to reclaim storage.
171+ //
177172 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.
178176}
179177
180178// A dataList is a list of []byte.
@@ -210,15 +208,6 @@ func (dl *dataList) removeFirst() int {
210208 return r
211209}
212210
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-
222211// A MemoryEventStore is an [EventStore] backed by memory.
223212type MemoryEventStore struct {
224213 mu sync.Mutex
@@ -267,9 +256,8 @@ func NewMemoryEventStore(opts *MemoryEventStoreOptions) *MemoryEventStore {
267256 }
268257}
269258
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 {
273261 s .mu .Lock ()
274262 defer s .mu .Unlock ()
275263
@@ -288,9 +276,13 @@ func (s *MemoryEventStore) AppendEvent(_ context.Context, sessionID string, stre
288276 s .purge ()
289277 dl .appendData (data )
290278 s .nBytes += len (data )
291- return dl . lastIndex (), nil
279+ return nil
292280}
293281
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+
294286// After implements [EventStore.After].
295287func (s * MemoryEventStore ) After (_ context.Context , sessionID string , streamID StreamID , index int ) iter.Seq2 [[]byte , error ] {
296288 // Return the data items to yield.
@@ -306,10 +298,12 @@ func (s *MemoryEventStore) After(_ context.Context, sessionID string, streamID S
306298 if ! ok {
307299 return nil , fmt .Errorf ("MemoryEventStore.After: unknown stream ID %v in session %q" , streamID , sessionID )
308300 }
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 )
311305 }
312- return slices .Clone (dl .data [index - dl .first :]), nil
306+ return slices .Clone (dl .data [start - dl .first :]), nil
313307 }
314308
315309 return func (yield func ([]byte , error ) bool ) {
@@ -326,26 +320,6 @@ func (s *MemoryEventStore) After(_ context.Context, sessionID string, streamID S
326320 }
327321}
328322
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-
349323// SessionClosed implements [EventStore.SessionClosed].
350324func (s * MemoryEventStore ) SessionClosed (_ context.Context , sessionID string ) error {
351325 s .mu .Lock ()
0 commit comments