@@ -6,11 +6,11 @@ import (
66 "fmt"
77 "io"
88 "net/http"
9- "strings"
109)
1110
1211type QuickwitIndexMetadata struct {
1312 IndexConfig struct {
13+ IndexID string `json:"index_id"`
1414 DocMapping struct {
1515 TimestampField string `json:"timestamp_field"`
1616 FieldMappings []FieldMappings `json:"field_mappings"`
@@ -23,6 +23,7 @@ type QuickwitCreationErrorPayload struct {
2323 StatusCode int `json:"status"`
2424}
2525
26+ // TODO: Revamp error handling
2627func NewErrorCreationPayload (statusCode int , message string ) error {
2728 var payload QuickwitCreationErrorPayload
2829 payload .Message = message
@@ -35,124 +36,73 @@ func NewErrorCreationPayload(statusCode int, message string) error {
3536 return errors .New (string (json ))
3637}
3738
38- // TODO: refactor either by using a timestamp alias suppprted by quickwit
39- // or by only using the `GetTimestampFieldFromIndexPattern` once the endpoint
40- // /indexes?index_id_pattern= is supported, which is after the next quickwit release > 0.7.1
41- func GetTimestampFieldInfos (index string , qwickwitUrl string , cli * http.Client ) (string , string , error ) {
42- if strings .Contains (index , "*" ) || strings .Contains (index , "," ) {
43- return GetTimestampFieldFromIndexPattern (index , qwickwitUrl , cli )
39+ func FilterErrorResponses (r * http.Response ) (* http.Response , error ) {
40+ if r .StatusCode < 200 || r .StatusCode >= 400 {
41+ body , err := io .ReadAll (r .Body )
42+ if err != nil {
43+ return nil , NewErrorCreationPayload (r .StatusCode , fmt .Errorf ("failed to read error body: err = %w" , err ).Error ())
44+ }
45+ return nil , NewErrorCreationPayload (r .StatusCode , fmt .Sprintf ("error = %s" , (body )))
4446 }
45- return GetTimestampFieldFromIndex ( index , qwickwitUrl , cli )
47+ return r , nil
4648}
4749
48- func GetTimestampFieldFromIndex (index string , qwickwitUrl string , cli * http.Client ) (string , string , error ) {
49- mappingEndpointUrl := qwickwitUrl + "/indexes/" + index
50- qwlog .Debug ("Calling quickwit endpoint: " + mappingEndpointUrl )
51- r , err := cli .Get (mappingEndpointUrl )
52- if err != nil {
53- errMsg := fmt .Sprintf ("Error when calling url = %s: err = %s" , mappingEndpointUrl , err .Error ())
54- qwlog .Error (errMsg )
55- return "" , "" , err
50+ func GetTimestampFieldInfos (indexMetadataList []QuickwitIndexMetadata ) (string , string , error ) {
51+ if len (indexMetadataList ) == 0 {
52+ return "" , "" , fmt .Errorf ("index metadata list is empty" )
5653 }
57- defer r .Body .Close ()
58-
59- statusCode := r .StatusCode
6054
61- if statusCode < 200 || statusCode >= 400 {
62- errMsg := fmt .Sprintf ("Error when calling url = %s" , mappingEndpointUrl )
63- qwlog .Error (errMsg )
64- return "" , "" , NewErrorCreationPayload (statusCode , errMsg )
55+ refTimestampFieldName , refTimestampOutputFormat := FindTimestampFieldInfos (indexMetadataList [0 ])
56+ if refTimestampFieldName == "" || refTimestampOutputFormat == "" {
57+ return "" , "" , fmt .Errorf ("Invalid timestamp field infos for %s: %s, %s" , indexMetadataList [0 ].IndexConfig .IndexID , refTimestampFieldName , refTimestampOutputFormat )
6558 }
6659
67- body , err := io .ReadAll (r .Body )
68- if err != nil {
69- errMsg := fmt .Sprintf ("Error when calling url = %s: err = %s" , mappingEndpointUrl , err .Error ())
70- qwlog .Error (errMsg )
71- return "" , "" , NewErrorCreationPayload (statusCode , errMsg )
60+ for _ , indexMetadata := range indexMetadataList [1 :] {
61+ timestampFieldName , timestampOutputFormat := FindTimestampFieldInfos (indexMetadata )
62+
63+ if timestampFieldName != refTimestampFieldName || timestampOutputFormat != refTimestampOutputFormat {
64+ return "" , "" , fmt .Errorf ("Indexes matching pattern have incompatible timestamp fields, found: %s (%s) and %s (%s)" , refTimestampFieldName , refTimestampOutputFormat , timestampFieldName , timestampOutputFormat )
65+ }
7266 }
7367
74- return DecodeTimestampFieldFromIndexConfig ( body )
68+ return refTimestampFieldName , refTimestampOutputFormat , nil
7569}
7670
77- func GetTimestampFieldFromIndexPattern (indexPattern string , qwickwitUrl string , cli * http.Client ) (string , string , error ) {
71+ func GetIndexesMetadata (indexPattern string , qwickwitUrl string , cli * http.Client ) ([] QuickwitIndexMetadata , error ) {
7872 mappingEndpointUrl := qwickwitUrl + "/indexes?index_id_patterns=" + indexPattern
7973 qwlog .Debug ("Calling quickwit endpoint: " + mappingEndpointUrl )
8074 r , err := cli .Get (mappingEndpointUrl )
8175 if err != nil {
82- errMsg := fmt .Sprintf ("Error when calling url = %s: err = %s" , mappingEndpointUrl , err .Error ())
83- qwlog .Error (errMsg )
84- return "" , "" , err
76+ return nil , fmt .Errorf ("Error when calling url = %s: %w" , mappingEndpointUrl , err )
8577 }
8678 defer r .Body .Close ()
8779
88- statusCode := r .StatusCode
89-
90- if statusCode < 200 || statusCode >= 400 {
91- errMsg := fmt .Sprintf ("Error when calling url = %s" , mappingEndpointUrl )
92- qwlog .Error (errMsg )
93- return "" , "" , NewErrorCreationPayload (statusCode , errMsg )
80+ r , err = FilterErrorResponses (r )
81+ if err != nil {
82+ return nil , fmt .Errorf ("API returned invalid response: %w" , err )
9483 }
9584
9685 body , err := io .ReadAll (r .Body )
9786 if err != nil {
98- errMsg := fmt .Sprintf ("Error when calling url = %s: err = %s" , mappingEndpointUrl , err .Error ())
99- qwlog .Error (errMsg )
100- return "" , "" , NewErrorCreationPayload (statusCode , errMsg )
87+ return nil , fmt .Errorf ("failed to read response body: %w" , err )
10188 }
10289
103- return DecodeTimestampFieldFromIndexConfigs (body )
104- }
105-
106- func DecodeTimestampFieldFromIndexConfigs (body []byte ) (string , string , error ) {
10790 var payload []QuickwitIndexMetadata
108- err : = json .Unmarshal (body , & payload )
91+ err = json .Unmarshal (body , & payload )
10992 if err != nil {
110- errMsg := fmt .Sprintf ("Unmarshalling body error: err = %s, body = %s" , err .Error (), (body ))
111- qwlog .Error (errMsg )
112- return "" , "" , NewErrorCreationPayload (500 , errMsg )
113- }
114-
115- var refTimestampFieldName string = ""
116- var refTimestampOutputFormat string = ""
117- var timestampFieldName string = ""
118- var timestampOutputFormat string = ""
119-
120- for _ , indexMetadata := range payload {
121- timestampFieldName = indexMetadata .IndexConfig .DocMapping .TimestampField
122- timestampOutputFormat , _ = FindTimeStampFormat (timestampFieldName , nil , indexMetadata .IndexConfig .DocMapping .FieldMappings )
123-
124- if refTimestampFieldName == "" {
125- refTimestampFieldName = timestampFieldName
126- refTimestampOutputFormat = timestampOutputFormat
127- continue
128- }
129-
130- if timestampFieldName != refTimestampFieldName || timestampOutputFormat != refTimestampOutputFormat {
131- errMsg := fmt .Sprintf ("Index matching the pattern should have the same timestamp fields, two found: %s (%s) and %s (%s)" , refTimestampFieldName , refTimestampOutputFormat , timestampFieldName , timestampOutputFormat )
132- qwlog .Error (errMsg )
133- return "" , "" , NewErrorCreationPayload (400 , errMsg )
134- }
93+ return nil , fmt .Errorf ("failed to unmarshal response body: %w" , err )
13594 }
13695
137- qwlog .Debug (fmt .Sprintf ("Found timestampFieldName = %s, timestamptOutputFormat = %s" , timestampFieldName , timestampOutputFormat ))
138- return timestampFieldName , timestampOutputFormat , nil
96+ return payload , nil
13997}
14098
141- func DecodeTimestampFieldFromIndexConfig (body []byte ) (string , string , error ) {
142- var payload QuickwitIndexMetadata
143- err := json .Unmarshal (body , & payload )
144- if err != nil {
145- errMsg := fmt .Sprintf ("Unmarshalling body error: err = %s, body = %s" , err .Error (), (body ))
146- qwlog .Error (errMsg )
147- return "" , "" , NewErrorCreationPayload (500 , errMsg )
148- }
149- timestampFieldName := payload .IndexConfig .DocMapping .TimestampField
150- timestampFieldFormat , _ := FindTimeStampFormat (timestampFieldName , nil , payload .IndexConfig .DocMapping .FieldMappings )
151- qwlog .Debug (fmt .Sprintf ("Found timestampFieldName = %s" , timestampFieldName ))
152- return timestampFieldName , timestampFieldFormat , nil
99+ func FindTimestampFieldInfos (indexMetadata QuickwitIndexMetadata ) (string , string ) {
100+ timestampFieldName := indexMetadata .IndexConfig .DocMapping .TimestampField
101+ timestampOutputFormat , _ := FindTimestampFormat (timestampFieldName , nil , indexMetadata .IndexConfig .DocMapping .FieldMappings )
102+ return timestampFieldName , timestampOutputFormat
153103}
154104
155- func FindTimeStampFormat (timestampFieldName string , parentName * string , fieldMappings []FieldMappings ) (string , bool ) {
105+ func FindTimestampFormat (timestampFieldName string , parentName * string , fieldMappings []FieldMappings ) (string , bool ) {
156106 if nil == fieldMappings {
157107 return "" , false
158108 }
@@ -166,7 +116,7 @@ func FindTimeStampFormat(timestampFieldName string, parentName *string, fieldMap
166116 if field .Type == "datetime" && fieldName == timestampFieldName && nil != field .OutputFormat {
167117 return * field .OutputFormat , true
168118 } else if field .Type == "object" && nil != field .FieldMappings {
169- return FindTimeStampFormat (timestampFieldName , & field .Name , field .FieldMappings )
119+ return FindTimestampFormat (timestampFieldName , & field .Name , field .FieldMappings )
170120 }
171121 }
172122
0 commit comments