diff --git a/storage/api.go b/storage/api.go index ff0c7461..6cb28e6a 100644 --- a/storage/api.go +++ b/storage/api.go @@ -73,8 +73,13 @@ type VectorWritableStorage interface { // The PeekableStorage.Peek method is essentially the same as ReadableStorage.Get -- // but by contrast, ReadableStorage is expected to return a safe copy. // PeekableStorage can be used when the caller knows they will not mutate the returned slice. +// +// An io.Closer is returned along with the byte slice. +// The Close method on the Closer must be called when the caller is done with the byte slice; +// otherwise, memory leaks may result. +// (Implementers of this interface may be expecting to reuse the byte slice after Close is called.) type PeekableStorage interface { - Peek(ctx context.Context, key string) ([]byte, error) + Peek(ctx context.Context, key string) ([]byte, io.Closer, error) } // the following are all hypothetical additional future interfaces (in varying degress of speculativeness): diff --git a/storage/funcs.go b/storage/funcs.go index 136e5b56..1a3daebc 100644 --- a/storage/funcs.go +++ b/storage/funcs.go @@ -95,11 +95,21 @@ func PutVec(ctx context.Context, store WritableStorage, key string, blobVec [][] // This function will feature-detect the PeekableStorage interface, and use that if possible; // otherwise it will fall back to using basic ReadableStorage methods transparently // (meaning that a no-copy fastpath simply wasn't available). -func Peek(ctx context.Context, store ReadableStorage, key string) ([]byte, error) { +// +// An io.Closer is returned along with the byte slice. +// The Close method on the Closer must be called when the caller is done with the byte slice; +// otherwise, memory leaks may result. +// (Implementers of this interface may be expecting to reuse the byte slice after Close is called.) +func Peek(ctx context.Context, store ReadableStorage, key string) ([]byte, io.Closer, error) { // Prefer the feature itself, first. if peekable, ok := store.(PeekableStorage); ok { return peekable.Peek(ctx, key) } // Fallback to basic. - return store.Get(ctx, key) + bs, err := store.Get(ctx, key) + return bs, noopCloser{}, err } + +type noopCloser struct{} + +func (noopCloser) Close() error { return nil }