@@ -20,8 +20,11 @@ var _ Indexer = &ElasticSearchIndexer{}
2020
2121// ElasticSearchIndexer implements Indexer interface
2222type ElasticSearchIndexer struct {
23- client * elastic.Client
24- indexerName string
23+ client * elastic.Client
24+ indexerName string
25+ available bool
26+ availabilityCallback func (bool )
27+ stopTimer chan struct {}
2528}
2629
2730type elasticLogger struct {
@@ -56,10 +59,27 @@ func NewElasticSearchIndexer(url, indexerName string) (*ElasticSearchIndexer, er
5659 return nil , err
5760 }
5861
59- return & ElasticSearchIndexer {
62+ indexer := & ElasticSearchIndexer {
6063 client : client ,
6164 indexerName : indexerName ,
62- }, nil
65+ available : true ,
66+ stopTimer : make (chan struct {}),
67+ }
68+
69+ ticker := time .NewTicker (10 * time .Second )
70+ go func () {
71+ for {
72+ select {
73+ case <- ticker .C :
74+ indexer .checkAvailability ()
75+ case <- indexer .stopTimer :
76+ ticker .Stop ()
77+ return
78+ }
79+ }
80+ }()
81+
82+ return indexer , nil
6383}
6484
6585const (
@@ -96,15 +116,15 @@ func (b *ElasticSearchIndexer) Init() (bool, error) {
96116 ctx := context .Background ()
97117 exists , err := b .client .IndexExists (b .indexerName ).Do (ctx )
98118 if err != nil {
99- return false , err
119+ return false , b . checkError ( err )
100120 }
101121
102122 if ! exists {
103123 mapping := defaultMapping
104124
105125 createIndex , err := b .client .CreateIndex (b .indexerName ).BodyString (mapping ).Do (ctx )
106126 if err != nil {
107- return false , err
127+ return false , b . checkError ( err )
108128 }
109129 if ! createIndex .Acknowledged {
110130 return false , errors .New ("init failed" )
@@ -115,6 +135,16 @@ func (b *ElasticSearchIndexer) Init() (bool, error) {
115135 return true , nil
116136}
117137
138+ // SetAvailabilityChangeCallback sets callback that will be triggered when availability changes
139+ func (b * ElasticSearchIndexer ) SetAvailabilityChangeCallback (callback func (bool )) {
140+ b .availabilityCallback = callback
141+ }
142+
143+ // Ping checks if elastic is available
144+ func (b * ElasticSearchIndexer ) Ping () bool {
145+ return b .available
146+ }
147+
118148// Index will save the index data
119149func (b * ElasticSearchIndexer ) Index (issues []* IndexerData ) error {
120150 if len (issues ) == 0 {
@@ -132,7 +162,7 @@ func (b *ElasticSearchIndexer) Index(issues []*IndexerData) error {
132162 "comments" : issue .Comments ,
133163 }).
134164 Do (context .Background ())
135- return err
165+ return b . checkError ( err )
136166 }
137167
138168 reqs := make ([]elastic.BulkableRequest , 0 )
@@ -155,7 +185,7 @@ func (b *ElasticSearchIndexer) Index(issues []*IndexerData) error {
155185 Index (b .indexerName ).
156186 Add (reqs ... ).
157187 Do (context .Background ())
158- return err
188+ return b . checkError ( err )
159189}
160190
161191// Delete deletes indexes by ids
@@ -167,7 +197,7 @@ func (b *ElasticSearchIndexer) Delete(ids ...int64) error {
167197 Index (b .indexerName ).
168198 Id (fmt .Sprintf ("%d" , ids [0 ])).
169199 Do (context .Background ())
170- return err
200+ return b . checkError ( err )
171201 }
172202
173203 reqs := make ([]elastic.BulkableRequest , 0 )
@@ -183,7 +213,7 @@ func (b *ElasticSearchIndexer) Delete(ids ...int64) error {
183213 Index (b .indexerName ).
184214 Add (reqs ... ).
185215 Do (context .Background ())
186- return err
216+ return b . checkError ( err )
187217}
188218
189219// Search searches for issues by given conditions.
@@ -207,7 +237,7 @@ func (b *ElasticSearchIndexer) Search(keyword string, repoIDs []int64, limit, st
207237 From (start ).Size (limit ).
208238 Do (context .Background ())
209239 if err != nil {
210- return nil , err
240+ return nil , b . checkError ( err )
211241 }
212242
213243 hits := make ([]Match , 0 , limit )
@@ -225,4 +255,32 @@ func (b *ElasticSearchIndexer) Search(keyword string, repoIDs []int64, limit, st
225255}
226256
227257// Close implements indexer
228- func (b * ElasticSearchIndexer ) Close () {}
258+ func (b * ElasticSearchIndexer ) Close () {
259+ close (b .stopTimer )
260+ }
261+
262+ func (b * ElasticSearchIndexer ) checkError (err error ) error {
263+ if elastic .IsConnErr (err ) && b .available {
264+ b .available = false
265+ if b .availabilityCallback != nil {
266+ b .availabilityCallback (b .available )
267+ }
268+ }
269+ return err
270+ }
271+
272+ func (b * ElasticSearchIndexer ) checkAvailability () {
273+ if b .available {
274+ return
275+ }
276+
277+ // Request cluster state to check if elastic is available again
278+ _ , err := b .client .ClusterState ().Do (context .Background ())
279+ if err != nil {
280+ return
281+ }
282+ b .available = true
283+ if b .availabilityCallback != nil {
284+ b .availabilityCallback (b .available )
285+ }
286+ }
0 commit comments