Skip to content

Commit 3b038d9

Browse files
committed
refactor: use a closeFn in the GetIndex instead of checking value
The closeFn implicitly checks the value as the implementation decides what to do (either do nothing or close the index). Calling the closeFn is safe and we don't need conditions.
1 parent 087d4a4 commit 3b038d9

File tree

3 files changed

+59
-62
lines changed

3 files changed

+59
-62
lines changed

services/search/pkg/engine/bleve.go

+16-29
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ func NewBleveEngine(indexGetter bleveEngine.IndexGetter, queryCreator searchQuer
6060
// This method is useful if "memory" and "persistent" (not "persistentScale")
6161
// index getters are used.
6262
func (b *Bleve) Close() error {
63-
bleveIndex, err := b.indexGetter.GetIndex()
63+
// regardless of the implementation, we want to close the index
64+
bleveIndex, _, err := b.indexGetter.GetIndex()
6465
if err != nil {
6566
return err
6667
}
@@ -121,13 +122,11 @@ func BuildBleveMapping() (mapping.IndexMapping, error) {
121122
// Search executes a search request operation within the index.
122123
// Returns a SearchIndexResponse object or an error.
123124
func (b *Bleve) Search(ctx context.Context, sir *searchService.SearchIndexRequest) (*searchService.SearchIndexResponse, error) {
124-
bleveIndex, err := b.indexGetter.GetIndex(bleveEngine.ReadOnly(true))
125+
bleveIndex, closeFn, err := b.indexGetter.GetIndex(bleveEngine.ReadOnly(true))
125126
if err != nil {
126127
return nil, err
127128
}
128-
if b.indexGetter.IndexCanBeClosed() {
129-
defer bleveIndex.Close()
130-
}
129+
defer closeFn()
131130

132131
createdQuery, err := b.queryCreator.Create(sir.Query)
133132
if err != nil {
@@ -243,26 +242,22 @@ func (b *Bleve) Search(ctx context.Context, sir *searchService.SearchIndexReques
243242

244243
// Upsert indexes or stores Resource data fields.
245244
func (b *Bleve) Upsert(id string, r Resource) error {
246-
bleveIndex, err := b.indexGetter.GetIndex()
245+
bleveIndex, closeFn, err := b.indexGetter.GetIndex()
247246
if err != nil {
248247
return err
249248
}
250-
if b.indexGetter.IndexCanBeClosed() {
251-
defer bleveIndex.Close()
252-
}
249+
defer closeFn()
253250

254251
return bleveIndex.Index(id, r)
255252
}
256253

257254
// Move updates the resource location and all of its necessary fields.
258255
func (b *Bleve) Move(id string, parentid string, target string) error {
259-
bleveIndex, err := b.indexGetter.GetIndex()
256+
bleveIndex, closeFn, err := b.indexGetter.GetIndex()
260257
if err != nil {
261258
return err
262259
}
263-
if b.indexGetter.IndexCanBeClosed() {
264-
defer bleveIndex.Close()
265-
}
260+
defer closeFn()
266261

267262
r, err := b.getResource(bleveIndex, id)
268263
if err != nil {
@@ -311,53 +306,45 @@ func (b *Bleve) Move(id string, parentid string, target string) error {
311306
// instead of removing the resource it just marks it as deleted!
312307
// can be undone
313308
func (b *Bleve) Delete(id string) error {
314-
bleveIndex, err := b.indexGetter.GetIndex()
309+
bleveIndex, closeFn, err := b.indexGetter.GetIndex()
315310
if err != nil {
316311
return err
317312
}
318-
if b.indexGetter.IndexCanBeClosed() {
319-
defer bleveIndex.Close()
320-
}
313+
defer closeFn()
321314

322315
return b.setDeleted(bleveIndex, id, true)
323316
}
324317

325318
// Restore is the counterpart to Delete.
326319
// It restores the resource which makes it available again.
327320
func (b *Bleve) Restore(id string) error {
328-
bleveIndex, err := b.indexGetter.GetIndex()
321+
bleveIndex, closeFn, err := b.indexGetter.GetIndex()
329322
if err != nil {
330323
return err
331324
}
332-
if b.indexGetter.IndexCanBeClosed() {
333-
defer bleveIndex.Close()
334-
}
325+
defer closeFn()
335326

336327
return b.setDeleted(bleveIndex, id, false)
337328
}
338329

339330
// Purge removes a resource from the index, irreversible operation.
340331
func (b *Bleve) Purge(id string) error {
341-
bleveIndex, err := b.indexGetter.GetIndex()
332+
bleveIndex, closeFn, err := b.indexGetter.GetIndex()
342333
if err != nil {
343334
return err
344335
}
345-
if b.indexGetter.IndexCanBeClosed() {
346-
defer bleveIndex.Close()
347-
}
336+
defer closeFn()
348337

349338
return bleveIndex.Delete(id)
350339
}
351340

352341
// DocCount returns the number of resources in the index.
353342
func (b *Bleve) DocCount() (uint64, error) {
354-
bleveIndex, err := b.indexGetter.GetIndex(bleveEngine.ReadOnly(true))
343+
bleveIndex, closeFn, err := b.indexGetter.GetIndex(bleveEngine.ReadOnly(true))
355344
if err != nil {
356345
return 0, err
357346
}
358-
if b.indexGetter.IndexCanBeClosed() {
359-
defer bleveIndex.Close()
360-
}
347+
defer closeFn()
361348

362349
return bleveIndex.DocCount()
363350
}

services/search/pkg/engine/bleve/index.go

+37-33
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,26 @@ import (
1212
// Implementations might differ in how the index is created and how the
1313
// index is gotten (reused, created on the fly, etc).
1414
//
15+
// The GetIndex method returns a function that must be called to close the index.
1516
// Some implementations might require the index to be kept opened, meaning
1617
// the index should be closed only when the application is shutting down. In
17-
// this case, IndexCanBeClosed should return false. If the index can be
18-
// closed and reopened safely at any time, IndexCanBeClosed should
19-
// return true.
18+
// this case, the returned function to close the index should do nothing (not
19+
// closing the index). If the index can be closed and reopened safely at any
20+
// time, the returned function should close the index.
21+
// Calling the returned function to close the index is fine regardless of the
22+
// implementation, and it will act as a no-op if the index should be kept opened.
2023
type IndexGetter interface {
21-
GetIndex(opts ...GetIndexOption) (bleve.Index, error)
22-
IndexCanBeClosed() bool
24+
GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error)
2325
}
2426

27+
// IndexGetterMemory is an implementation of IndexGetter that uses an in-memory
28+
// index. The implementation caches the index and returns the same index every
29+
// time GetIndex is called.
30+
// The data won't be persisted between runs, and closing the index will wipe
31+
// the data.
32+
// The close function returned by GetIndex won't do anything. The index should
33+
// be kept opened until the application is shutting down.
34+
// This is useful for testing and small datasets.
2535
type IndexGetterMemory struct {
2636
mapping mapping.IndexMapping
2737
index bleve.Index
@@ -39,25 +49,25 @@ func NewIndexGetterMemory(mapping mapping.IndexMapping) *IndexGetterMemory {
3949

4050
// GetIndex creates a new in-memory index every time it is called.
4151
// The options are ignored in this implementation.
42-
func (i *IndexGetterMemory) GetIndex(opts ...GetIndexOption) (bleve.Index, error) {
52+
func (i *IndexGetterMemory) GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error) {
4353
if i.index != nil {
44-
return i.index, nil
54+
return i.index, func() {}, nil
4555
}
4656

4757
index, err := bleve.NewMemOnly(i.mapping)
4858
if err != nil {
49-
return nil, err
59+
return nil, func() {}, err
5060
}
5161

5262
i.index = index
53-
return i.index, nil
54-
}
55-
56-
// IndexCanBeClosed returns false, meaning the index must be kept opened.
57-
func (i *IndexGetterMemory) IndexCanBeClosed() bool {
58-
return false
63+
return i.index, func() {}, nil
5964
}
6065

66+
// IndexGetterPersistent is an implementation of IndexGetter that persists the
67+
// index on the filesystem. The implementation caches the index and returns the
68+
// same index every time GetIndex is called.
69+
// The close function returned by GetIndex won't do anything. The index should
70+
// be kept opened until the application is shutting down.
6171
type IndexGetterPersistent struct {
6272
rootDir string
6373
mapping mapping.IndexMapping
@@ -79,29 +89,29 @@ func NewIndexGetterPersistent(rootDir string, mapping mapping.IndexMapping) *Ind
7989

8090
// GetIndex returns the cached index. The options are ignored in this
8191
// implementation.
82-
func (i *IndexGetterPersistent) GetIndex(opts ...GetIndexOption) (bleve.Index, error) {
92+
func (i *IndexGetterPersistent) GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error) {
8393
if i.index != nil {
84-
return i.index, nil
94+
return i.index, func() {}, nil
8595
}
8696

8797
destination := filepath.Join(i.rootDir, "bleve")
8898
index, err := bleve.Open(destination)
8999
if errors.Is(bleve.ErrorIndexPathDoesNotExist, err) {
90100
index, err = bleve.New(destination, i.mapping)
91101
if err != nil {
92-
return nil, err
102+
return nil, func() {}, err
93103
}
94104
}
95105

96106
i.index = index
97-
return i.index, nil
98-
}
99-
100-
// IndexCanBeClosed returns false, meaning the index must be kept opened.
101-
func (i *IndexGetterPersistent) IndexCanBeClosed() bool {
102-
return false
107+
return i.index, func() {}, nil
103108
}
104109

110+
// IndexGetterPersistentScale is an implementation of IndexGetter that persists
111+
// the index on the filesystem. The implementation does not cache the index and
112+
// creates a new connection to the index every time GetIndex is called.
113+
// The close function returned by GetIndex must be called to close the index, as
114+
// soon as you the operations on the index are done.
105115
type IndexGetterPersistentScale struct {
106116
rootDir string
107117
mapping mapping.IndexMapping
@@ -124,7 +134,7 @@ func NewIndexGetterPersistentScale(rootDir string, mapping mapping.IndexMapping)
124134
// allow read-only operations to be performed in parallel.
125135
// In order to avoid blocking write operations, you should close the index
126136
// as soon as you are done with it.
127-
func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Index, error) {
137+
func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error) {
128138
options := newGetIndexOptions(opts...)
129139
destination := filepath.Join(i.rootDir, "bleve")
130140
params := map[string]interface{}{
@@ -134,17 +144,11 @@ func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Ind
134144
if errors.Is(bleve.ErrorIndexPathDoesNotExist, err) {
135145
index, err = bleve.New(destination, i.mapping)
136146
if err != nil {
137-
return nil, err
147+
return nil, func() {}, err
138148
}
139149

140-
return index, nil
150+
return index, func() { index.Close() }, nil
141151
}
142152

143-
return index, err
144-
}
145-
146-
// IndexCanBeClosed returns true, meaning the index can be closed and
147-
// reopened. You should close the index as soon as you are done with it.
148-
func (i *IndexGetterPersistentScale) IndexCanBeClosed() bool {
149-
return true
153+
return index, func() { index.Close() }, err
150154
}

services/search/pkg/engine/bleve/option.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package bleve
22

3+
// GetIndexOption is a function that sets some option for the GetIndex method.
34
type GetIndexOption func(o *GetIndexOptions)
45

6+
// GetIndexOptions contains the options for the GetIndex method.
57
type GetIndexOptions struct {
68
ReadOnly bool
79
}
810

11+
// ReadOnly is an option to opens the index in read-only mode.
12+
// This option should allow running multiple read-only operations in parallel.
13+
// The behavior of write operations is not defined when this option is used.
914
func ReadOnly(b bool) GetIndexOption {
1015
return func(o *GetIndexOptions) {
1116
o.ReadOnly = b
1217
}
1318
}
1419

20+
// newGetIndexOptions creates a new GetIndexOptions with the given options.
1521
func newGetIndexOptions(opts ...GetIndexOption) GetIndexOptions {
1622
o := GetIndexOptions{}
1723
for _, opt := range opts {

0 commit comments

Comments
 (0)