@@ -6,11 +6,11 @@ import (
6
6
"fmt"
7
7
"io"
8
8
"net/http"
9
- "strings"
10
9
)
11
10
12
11
type QuickwitIndexMetadata struct {
13
12
IndexConfig struct {
13
+ IndexID string `json:"index_id"`
14
14
DocMapping struct {
15
15
TimestampField string `json:"timestamp_field"`
16
16
FieldMappings []FieldMappings `json:"field_mappings"`
@@ -23,6 +23,7 @@ type QuickwitCreationErrorPayload struct {
23
23
StatusCode int `json:"status"`
24
24
}
25
25
26
+ // TODO: Revamp error handling
26
27
func NewErrorCreationPayload (statusCode int , message string ) error {
27
28
var payload QuickwitCreationErrorPayload
28
29
payload .Message = message
@@ -35,124 +36,73 @@ func NewErrorCreationPayload(statusCode int, message string) error {
35
36
return errors .New (string (json ))
36
37
}
37
38
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 )))
44
46
}
45
- return GetTimestampFieldFromIndex ( index , qwickwitUrl , cli )
47
+ return r , nil
46
48
}
47
49
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" )
56
53
}
57
- defer r .Body .Close ()
58
-
59
- statusCode := r .StatusCode
60
54
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 )
65
58
}
66
59
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
+ }
72
66
}
73
67
74
- return DecodeTimestampFieldFromIndexConfig ( body )
68
+ return refTimestampFieldName , refTimestampOutputFormat , nil
75
69
}
76
70
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 ) {
78
72
mappingEndpointUrl := qwickwitUrl + "/indexes?index_id_patterns=" + indexPattern
79
73
qwlog .Debug ("Calling quickwit endpoint: " + mappingEndpointUrl )
80
74
r , err := cli .Get (mappingEndpointUrl )
81
75
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 )
85
77
}
86
78
defer r .Body .Close ()
87
79
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 )
94
83
}
95
84
96
85
body , err := io .ReadAll (r .Body )
97
86
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 )
101
88
}
102
89
103
- return DecodeTimestampFieldFromIndexConfigs (body )
104
- }
105
-
106
- func DecodeTimestampFieldFromIndexConfigs (body []byte ) (string , string , error ) {
107
90
var payload []QuickwitIndexMetadata
108
- err : = json .Unmarshal (body , & payload )
91
+ err = json .Unmarshal (body , & payload )
109
92
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 )
135
94
}
136
95
137
- qwlog .Debug (fmt .Sprintf ("Found timestampFieldName = %s, timestamptOutputFormat = %s" , timestampFieldName , timestampOutputFormat ))
138
- return timestampFieldName , timestampOutputFormat , nil
96
+ return payload , nil
139
97
}
140
98
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
153
103
}
154
104
155
- func FindTimeStampFormat (timestampFieldName string , parentName * string , fieldMappings []FieldMappings ) (string , bool ) {
105
+ func FindTimestampFormat (timestampFieldName string , parentName * string , fieldMappings []FieldMappings ) (string , bool ) {
156
106
if nil == fieldMappings {
157
107
return "" , false
158
108
}
@@ -166,7 +116,7 @@ func FindTimeStampFormat(timestampFieldName string, parentName *string, fieldMap
166
116
if field .Type == "datetime" && fieldName == timestampFieldName && nil != field .OutputFormat {
167
117
return * field .OutputFormat , true
168
118
} else if field .Type == "object" && nil != field .FieldMappings {
169
- return FindTimeStampFormat (timestampFieldName , & field .Name , field .FieldMappings )
119
+ return FindTimestampFormat (timestampFieldName , & field .Name , field .FieldMappings )
170
120
}
171
121
}
172
122
0 commit comments