-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrap the code indexer #9476
Wrap the code indexer #9476
Changes from 1 commit
b4a7e45
cbdf6b3
9ebb311
7bff177
ebc9a6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright 2019 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package code | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
) | ||
|
||
var ( | ||
indexer = newWrappedIndexer() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indexer has to be wrapped to allow searches etc to hold whilst we are waiting for the indexer to boot up further we must not run functions on the indexer until it is completely ready. If the indexer is closed before its internal element is present then we will return a simple error rather than panic. |
||
) | ||
|
||
// ErrWrappedIndexerClosed is the error returned if the indexer was closed before it was ready | ||
var ErrWrappedIndexerClosed = fmt.Errorf("Indexer closed before ready") | ||
|
||
type wrappedIndexer struct { | ||
internal Indexer | ||
lock sync.RWMutex | ||
cond *sync.Cond | ||
closed bool | ||
} | ||
|
||
func newWrappedIndexer() *wrappedIndexer { | ||
w := &wrappedIndexer{} | ||
w.cond = sync.NewCond(w.lock.RLocker()) | ||
return w | ||
} | ||
|
||
func (w *wrappedIndexer) set(indexer Indexer) { | ||
w.lock.Lock() | ||
defer w.lock.Unlock() | ||
if w.closed { | ||
// Too late! | ||
indexer.Close() | ||
} | ||
w.internal = indexer | ||
w.cond.Broadcast() | ||
} | ||
|
||
func (w *wrappedIndexer) get() (Indexer, error) { | ||
w.lock.RLock() | ||
defer w.lock.RUnlock() | ||
if w.internal == nil { | ||
if w.closed { | ||
return nil, ErrWrappedIndexerClosed | ||
} | ||
w.cond.Wait() | ||
} | ||
return w.internal, nil | ||
} | ||
|
||
func (w *wrappedIndexer) Index(repoID int64) error { | ||
indexer, err := w.get() | ||
if err != nil { | ||
return err | ||
} | ||
return indexer.Index(repoID) | ||
} | ||
|
||
func (w *wrappedIndexer) Delete(repoID int64) error { | ||
indexer, err := w.get() | ||
if err != nil { | ||
return err | ||
} | ||
return indexer.Delete(repoID) | ||
} | ||
|
||
func (w *wrappedIndexer) Search(repoIDs []int64, keyword string, page, pageSize int) (int64, []*SearchResult, error) { | ||
indexer, err := w.get() | ||
if err != nil { | ||
return 0, nil, err | ||
} | ||
return indexer.Search(repoIDs, keyword, page, pageSize) | ||
|
||
} | ||
|
||
func (w *wrappedIndexer) Close() { | ||
w.lock.Lock() | ||
defer w.lock.Unlock() | ||
if w.closed { | ||
return | ||
} | ||
w.closed = true | ||
w.cond.Broadcast() | ||
if w.internal != nil { | ||
w.internal.Close() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once the indexer is running we should close it at Terminate not Shutdown. Things running in the ShutdownContext and up to HammerTime might still need to send data to the repo indexer.
If the indexer fails to be set up then we should close ASAP as we want gitea to stop ASAP.