-
Notifications
You must be signed in to change notification settings - Fork 6
/
util.go
99 lines (90 loc) · 2.05 KB
/
util.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
package es
import (
"context"
"fmt"
"time"
"github.com/rs/rest-layer/resource"
"github.com/rs/rest-layer/schema/query"
"gopkg.in/olivere/elastic.v5"
)
const (
etagField = "_etag"
updatedField = "_updated"
)
// buildDoc builds an ElasticSearch document from a resource.Item
func buildDoc(i *resource.Item) map[string]interface{} {
// Filter out id from the payload so we don't store it twice
d := map[string]interface{}{}
for k, v := range i.Payload {
if k != "id" {
d[k] = v
}
}
if i.ETag != "" {
d[etagField] = i.ETag
}
if !i.Updated.IsZero() {
d[updatedField] = i.Updated
}
return d
}
// buildItem builds a resource.Item from an ElasticSearch document
func buildItem(id string, d map[string]interface{}) *resource.Item {
i := resource.Item{
ID: id,
Payload: map[string]interface{}{"id": id},
}
if etag, ok := d[etagField].(string); ok {
i.ETag = etag
}
if updated, ok := d[updatedField].(time.Time); ok {
i.Updated = updated
}
for k, v := range d {
if k != etagField && k != updatedField {
i.Payload[k] = v
}
}
return &i
}
func isConflict(err interface{}) bool {
if elastic.IsConflict(err) {
return true
}
if e, ok := err.(*elastic.ErrorDetails); ok {
return e.Type == "version_conflict_engine_exception"
}
return false
}
// translateError translates some generic errors to REST Layer errors
func translateError(err *error) bool {
if elastic.IsTimeout(*err) {
*err = context.DeadlineExceeded
return true
} else if isConflict(*err) {
*err = resource.ErrConflict
return true
} else if elastic.IsNotFound(*err) {
*err = resource.ErrNotFound
return true
}
return false
}
// ctxTimeout returns an ES compatible timeout argument if context has a deadline
func ctxTimeout(ctx context.Context) string {
if dl, ok := ctx.Deadline(); ok {
dur := dl.Sub(time.Now())
if dur < 0 {
dur = 0
}
return fmt.Sprintf("%dms", int(dur/time.Millisecond))
}
return ""
}
func valuesToInterface(v []query.Value) []interface{} {
I := make([]interface{}, len(v))
for i, _v := range v {
I[i] = _v
}
return I
}