-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsdk.go
152 lines (139 loc) · 3.17 KB
/
sdk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package database_sdk
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
)
var healthcheckPath = "%s/healthcheck"
var contentType = "application/json"
var apiPath = "%s/api/%s/documents"
var queryParams = "?q=%s&limit=%d&offset=%d"
var DatabasePingErr = errors.New("can not ping database")
type Source struct {
Date time.Time `json:"date"`
Title string `json:"title"`
}
type RawData struct {
Source Source `json:"source"`
Url string `json:"url"`
Data string `json:"data"`
}
type Documents struct {
Documents []RawData `json:"documents"`
}
type ResponseData struct {
Source Source
Url string `json:"url"`
}
// DBClient struct consist payload and collection name
type DBClient struct {
url string
c *http.Client
}
// CustomError wrap error with error code from database
type CustomError struct {
error
code int
}
type simpleMessage struct {
Msg string `json:"msg"`
}
func wrap(msg string, code int, err error) error {
return CustomError{error: fmt.Errorf("unexpected err: %w, body %s", err, msg), code: code}
}
// NewDBClient return new instance of DBClient
func NewDBClient(url string) (*DBClient, error) {
db := &DBClient{
url: url,
c: &http.Client{
Timeout: 60 * time.Second,
},
}
resp, err := db.c.Get(fmt.Sprintf(healthcheckPath, url))
if err != nil {
return nil, DatabasePingErr
}
if resp.StatusCode != http.StatusOK {
return nil, DatabasePingErr
}
return db, nil
}
// SaveData RawData to PolySE Database
func (d *DBClient) SaveData(collectionName string, data Documents) (*Documents, error) {
requestBody, err := json.Marshal(data)
if err != nil {
return nil, fmt.Errorf("can't perform request: %w", err)
}
resp, err := d.c.Post(
fmt.Sprintf(
apiPath,
d.url,
url.PathEscape(collectionName),
),
contentType,
bytes.NewBuffer(requestBody),
)
if err != nil {
return nil, err
}
defer func() {
err = resp.Body.Close()
}()
var res Documents
err = json.NewDecoder(resp.Body).Decode(&res)
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusCreated {
return &res, nil
}
var sm simpleMessage
err = json.NewDecoder(resp.Body).Decode(&sm)
if err != nil {
raw, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, wrap(string(raw), resp.StatusCode, err)
}
return nil, wrap(sm.Msg, resp.StatusCode, err)
}
// GetData returns data from PolySE Database
func (d *DBClient) GetData(collectionName, searchPhrase string, limit, offset int) ([]ResponseData, error) {
response, err := d.c.Get(
fmt.Sprintf(
apiPath+queryParams,
d.url,
url.PathEscape(collectionName),
url.PathEscape(searchPhrase),
limit,
offset,
),
)
if err != nil {
return nil, err
}
raw, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
if response.StatusCode != http.StatusOK {
var sm simpleMessage
err := json.Unmarshal(raw, &sm)
if err != nil {
return nil, wrap(string(raw), response.StatusCode, err)
}
return nil, wrap(sm.Msg, response.StatusCode, err)
}
var result []ResponseData
err = json.Unmarshal(raw, &result)
if err != nil {
return nil, err
}
return result, nil
}