code.gitea.io/gitea@v1.19.3/modules/indexer/code/wrapped.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package code 5 6 import ( 7 "context" 8 "fmt" 9 "sync" 10 11 repo_model "code.gitea.io/gitea/models/repo" 12 "code.gitea.io/gitea/modules/log" 13 ) 14 15 var indexer = newWrappedIndexer() 16 17 // ErrWrappedIndexerClosed is the error returned if the indexer was closed before it was ready 18 var ErrWrappedIndexerClosed = fmt.Errorf("Indexer closed before ready") 19 20 type wrappedIndexer struct { 21 internal Indexer 22 lock sync.RWMutex 23 cond *sync.Cond 24 closed bool 25 } 26 27 func newWrappedIndexer() *wrappedIndexer { 28 w := &wrappedIndexer{} 29 w.cond = sync.NewCond(w.lock.RLocker()) 30 return w 31 } 32 33 func (w *wrappedIndexer) set(indexer Indexer) { 34 w.lock.Lock() 35 defer w.lock.Unlock() 36 if w.closed { 37 // Too late! 38 indexer.Close() 39 } 40 w.internal = indexer 41 w.cond.Broadcast() 42 } 43 44 func (w *wrappedIndexer) get() (Indexer, error) { 45 w.lock.RLock() 46 defer w.lock.RUnlock() 47 if w.internal == nil { 48 if w.closed { 49 return nil, ErrWrappedIndexerClosed 50 } 51 w.cond.Wait() 52 if w.closed { 53 return nil, ErrWrappedIndexerClosed 54 } 55 } 56 return w.internal, nil 57 } 58 59 // SetAvailabilityChangeCallback sets callback that will be triggered when availability changes 60 func (w *wrappedIndexer) SetAvailabilityChangeCallback(callback func(bool)) { 61 indexer, err := w.get() 62 if err != nil { 63 log.Error("Failed to get indexer: %v", err) 64 return 65 } 66 indexer.SetAvailabilityChangeCallback(callback) 67 } 68 69 // Ping checks if elastic is available 70 func (w *wrappedIndexer) Ping() bool { 71 indexer, err := w.get() 72 if err != nil { 73 log.Warn("Failed to get indexer: %v", err) 74 return false 75 } 76 return indexer.Ping() 77 } 78 79 func (w *wrappedIndexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *repoChanges) error { 80 indexer, err := w.get() 81 if err != nil { 82 return err 83 } 84 return indexer.Index(ctx, repo, sha, changes) 85 } 86 87 func (w *wrappedIndexer) Delete(repoID int64) error { 88 indexer, err := w.get() 89 if err != nil { 90 return err 91 } 92 return indexer.Delete(repoID) 93 } 94 95 func (w *wrappedIndexer) Search(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error) { 96 indexer, err := w.get() 97 if err != nil { 98 return 0, nil, nil, err 99 } 100 return indexer.Search(ctx, repoIDs, language, keyword, page, pageSize, isMatch) 101 } 102 103 func (w *wrappedIndexer) Close() { 104 w.lock.Lock() 105 defer w.lock.Unlock() 106 if w.closed { 107 return 108 } 109 w.closed = true 110 w.cond.Broadcast() 111 if w.internal != nil { 112 w.internal.Close() 113 } 114 }