@@ -11,6 +11,7 @@ import (
1111 "time"
1212
1313 "github.com/elastic/go-elasticsearch/v7"
14+ "github.com/elastic/go-elasticsearch/v7/esapi"
1415 "github.com/odpf/columbus/models"
1516 "github.com/olivere/elastic/v7"
1617)
@@ -92,6 +93,41 @@ func (repo *RecordRepository) writeInsertAction(w io.Writer, record models.Recor
9293 return json .NewEncoder (w ).Encode (action )
9394}
9495
96+ func (repo * RecordRepository ) GetAllIterator (ctx context.Context ) (models.RecordIterator , error ) {
97+ body , err := repo .getAllQuery (models.RecordFilter {})
98+ if err != nil {
99+ return nil , fmt .Errorf ("error building search query: %w" , err )
100+ }
101+
102+ resp , err := repo .cli .Search (
103+ repo .cli .Search .WithIndex (repo .recordType .Name ),
104+ repo .cli .Search .WithBody (body ),
105+ repo .cli .Search .WithScroll (defaultScrollTimeout ),
106+ repo .cli .Search .WithSize (defaultScrollBatchSize ),
107+ repo .cli .Search .WithContext (ctx ),
108+ )
109+ if err != nil {
110+ return nil , fmt .Errorf ("error executing search: %w" , err )
111+ }
112+ if resp .IsError () {
113+ return nil , fmt .Errorf ("error response from elasticsearch: %s" , errorReasonFromResponse (resp ))
114+ }
115+
116+ var response searchResponse
117+ err = json .NewDecoder (resp .Body ).Decode (& response )
118+ if err != nil {
119+ return nil , fmt .Errorf ("error decoding es response: %w" , err )
120+ }
121+ var results = repo .toRecordList (response )
122+ it := recordIterator {
123+ resp : resp ,
124+ records : results ,
125+ scrollID : response .ScrollID ,
126+ repo : repo ,
127+ }
128+ return & it , nil
129+ }
130+
95131func (repo * RecordRepository ) GetAll (ctx context.Context , filters models.RecordFilter ) ([]models.Record , error ) {
96132 // XXX(Aman): we should probably think about result ordering, if the client
97133 // is going to slice the data for pagination. Does ES guarantee the result order?
@@ -246,6 +282,35 @@ func (repo *RecordRepository) Delete(ctx context.Context, id string) error {
246282 return nil
247283}
248284
285+ // recordIterator is the internal implementation of models.RecordIterator by RecordRepository
286+ type recordIterator struct {
287+ resp * esapi.Response
288+ records []models.Record
289+ repo * RecordRepository
290+ scrollID string
291+ }
292+
293+ func (it * recordIterator ) Scan () bool {
294+ return len (strings .TrimSpace (it .scrollID )) > 0
295+ }
296+
297+ func (it * recordIterator ) Next () (prev []models.Record ) {
298+ prev = it .records
299+ var err error
300+ it .records , it .scrollID , err = it .repo .scrollRecords (context .Background (), it .scrollID )
301+ if err != nil {
302+ panic ("error scrolling results:" + err .Error ())
303+ }
304+ if len (it .records ) == 0 {
305+ it .scrollID = ""
306+ }
307+ return
308+ }
309+
310+ func (it * recordIterator ) Close () error {
311+ return it .resp .Body .Close ()
312+ }
313+
249314// RecordRepositoryFactory can be used to construct a RecordRepository
250315// for a certain type
251316type RecordRepositoryFactory struct {
0 commit comments