@@ -20,8 +20,11 @@ var _ Indexer = &ElasticSearchIndexer{}
20
20
21
21
// ElasticSearchIndexer implements Indexer interface
22
22
type 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 {}
25
28
}
26
29
27
30
type elasticLogger struct {
@@ -56,10 +59,27 @@ func NewElasticSearchIndexer(url, indexerName string) (*ElasticSearchIndexer, er
56
59
return nil , err
57
60
}
58
61
59
- return & ElasticSearchIndexer {
62
+ indexer := & ElasticSearchIndexer {
60
63
client : client ,
61
64
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
63
83
}
64
84
65
85
const (
@@ -96,15 +116,15 @@ func (b *ElasticSearchIndexer) Init() (bool, error) {
96
116
ctx := context .Background ()
97
117
exists , err := b .client .IndexExists (b .indexerName ).Do (ctx )
98
118
if err != nil {
99
- return false , err
119
+ return false , b . checkError ( err )
100
120
}
101
121
102
122
if ! exists {
103
123
mapping := defaultMapping
104
124
105
125
createIndex , err := b .client .CreateIndex (b .indexerName ).BodyString (mapping ).Do (ctx )
106
126
if err != nil {
107
- return false , err
127
+ return false , b . checkError ( err )
108
128
}
109
129
if ! createIndex .Acknowledged {
110
130
return false , errors .New ("init failed" )
@@ -115,6 +135,16 @@ func (b *ElasticSearchIndexer) Init() (bool, error) {
115
135
return true , nil
116
136
}
117
137
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
+
118
148
// Index will save the index data
119
149
func (b * ElasticSearchIndexer ) Index (issues []* IndexerData ) error {
120
150
if len (issues ) == 0 {
@@ -132,7 +162,7 @@ func (b *ElasticSearchIndexer) Index(issues []*IndexerData) error {
132
162
"comments" : issue .Comments ,
133
163
}).
134
164
Do (context .Background ())
135
- return err
165
+ return b . checkError ( err )
136
166
}
137
167
138
168
reqs := make ([]elastic.BulkableRequest , 0 )
@@ -155,7 +185,7 @@ func (b *ElasticSearchIndexer) Index(issues []*IndexerData) error {
155
185
Index (b .indexerName ).
156
186
Add (reqs ... ).
157
187
Do (context .Background ())
158
- return err
188
+ return b . checkError ( err )
159
189
}
160
190
161
191
// Delete deletes indexes by ids
@@ -167,7 +197,7 @@ func (b *ElasticSearchIndexer) Delete(ids ...int64) error {
167
197
Index (b .indexerName ).
168
198
Id (fmt .Sprintf ("%d" , ids [0 ])).
169
199
Do (context .Background ())
170
- return err
200
+ return b . checkError ( err )
171
201
}
172
202
173
203
reqs := make ([]elastic.BulkableRequest , 0 )
@@ -183,7 +213,7 @@ func (b *ElasticSearchIndexer) Delete(ids ...int64) error {
183
213
Index (b .indexerName ).
184
214
Add (reqs ... ).
185
215
Do (context .Background ())
186
- return err
216
+ return b . checkError ( err )
187
217
}
188
218
189
219
// Search searches for issues by given conditions.
@@ -207,7 +237,7 @@ func (b *ElasticSearchIndexer) Search(keyword string, repoIDs []int64, limit, st
207
237
From (start ).Size (limit ).
208
238
Do (context .Background ())
209
239
if err != nil {
210
- return nil , err
240
+ return nil , b . checkError ( err )
211
241
}
212
242
213
243
hits := make ([]Match , 0 , limit )
@@ -225,4 +255,32 @@ func (b *ElasticSearchIndexer) Search(keyword string, repoIDs []int64, limit, st
225
255
}
226
256
227
257
// 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