Skip to content

Commit 6df657b

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 6df657b

File tree

3 files changed

+62
-62
lines changed

3 files changed

+62
-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

+40-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,26 @@ 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) {
53+
closeFn := func() {} // no-op
4354
if i.index != nil {
44-
return i.index, nil
55+
return i.index, closeFn, nil
4556
}
4657

4758
index, err := bleve.NewMemOnly(i.mapping)
4859
if err != nil {
49-
return nil, err
60+
return nil, closeFn, err
5061
}
5162

5263
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
64+
return i.index, closeFn, nil
5965
}
6066

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

8091
// GetIndex returns the cached index. The options are ignored in this
8192
// implementation.
82-
func (i *IndexGetterPersistent) GetIndex(opts ...GetIndexOption) (bleve.Index, error) {
93+
func (i *IndexGetterPersistent) GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error) {
94+
closeFn := func() {} // no-op
8395
if i.index != nil {
84-
return i.index, nil
96+
return i.index, closeFn, nil
8597
}
8698

8799
destination := filepath.Join(i.rootDir, "bleve")
88100
index, err := bleve.Open(destination)
89101
if errors.Is(bleve.ErrorIndexPathDoesNotExist, err) {
90102
index, err = bleve.New(destination, i.mapping)
91103
if err != nil {
92-
return nil, err
104+
return nil, closeFn, err
93105
}
94106
}
95107

96108
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
109+
return i.index, closeFn, nil
103110
}
104111

112+
// IndexGetterPersistentScale is an implementation of IndexGetter that persists
113+
// the index on the filesystem. The implementation does not cache the index and
114+
// creates a new connection to the index every time GetIndex is called.
115+
// The close function returned by GetIndex must be called to close the index, as
116+
// soon as you the operations on the index are done.
105117
type IndexGetterPersistentScale struct {
106118
rootDir string
107119
mapping mapping.IndexMapping
@@ -124,7 +136,7 @@ func NewIndexGetterPersistentScale(rootDir string, mapping mapping.IndexMapping)
124136
// allow read-only operations to be performed in parallel.
125137
// In order to avoid blocking write operations, you should close the index
126138
// as soon as you are done with it.
127-
func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Index, error) {
139+
func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Index, func(), error) {
128140
options := newGetIndexOptions(opts...)
129141
destination := filepath.Join(i.rootDir, "bleve")
130142
params := map[string]interface{}{
@@ -134,17 +146,12 @@ func (i *IndexGetterPersistentScale) GetIndex(opts ...GetIndexOption) (bleve.Ind
134146
if errors.Is(bleve.ErrorIndexPathDoesNotExist, err) {
135147
index, err = bleve.New(destination, i.mapping)
136148
if err != nil {
137-
return nil, err
149+
closeFn := func() {} // no-op
150+
return nil, closeFn, err
138151
}
139152

140-
return index, nil
153+
return index, func() { index.Close() }, nil
141154
}
142155

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
156+
return index, func() { index.Close() }, err
150157
}

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)