-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathglobal_index.go
137 lines (108 loc) · 4.34 KB
/
global_index.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
package djoemo
import (
"context"
"reflect"
"github.com/guregu/dynamo"
)
// GlobalIndex models a global secondary index used in a query
type GlobalIndex struct {
name string
dynamoClient *dynamo.DB
log logger
}
// GetItems by key; it accepts a key interface that is used to get the table name, hash key and range key if it exists; the output will be given in items
// returns true if items are found, returns false and nil if no items found, returns false and error in case of error
func (gi GlobalIndex) GetItems(key KeyInterface, items interface{}) (bool, error) {
return gi.GetItemsWithContext(context.TODO(), key, items)
}
// GetItem get item; it accepts a key interface that is used to get the table name, hash key and range key if it exists; the output will be given in item
// returns true if item is found, returns false and nil if no item found, returns false and an error in case of error
func (gi GlobalIndex) GetItem(key KeyInterface, item interface{}) (bool, error) {
return gi.GetItemWithContext(context.TODO(), key, item)
}
// GetItemWithContext item; it needs a key interface that is used to get the table name, hash key, and the range key if it exists; output will be contained in item; context is optional param, which used to enable log with context
func (gi GlobalIndex) GetItemWithContext(ctx context.Context, key KeyInterface, item interface{}) (bool, error) {
if err := isValidKey(key); err != nil {
gi.log.error(ctx, key.TableName(), err.Error())
return false, err
}
// by hash
query := gi.table(key.TableName()).Get(*key.HashKeyName(), key.HashKey())
// by range
if key.RangeKeyName() != nil && key.RangeKey() != nil {
query = query.Range(*key.RangeKeyName(), dynamo.Equal, key.RangeKey())
}
err := query.Index(gi.name).OneWithContext(ctx, item)
if err != nil {
if err == dynamo.ErrNotFound {
gi.log.info(ctx, key.TableName(), ErrNoItemFound.Error())
return false, nil
}
gi.log.error(ctx, key.TableName(), err.Error())
return false, err
}
return true, nil
}
// GetItemsWithContext queries multiple items by key (hash key) and returns it in the slice of items items
func (gi GlobalIndex) GetItemsWithContext(ctx context.Context, key KeyInterface, items interface{}) (bool, error) {
if err := isValidKey(key); err != nil {
gi.log.error(ctx, key.TableName(), err.Error())
return false, err
}
err := gi.table(key.TableName()).Get(*key.HashKeyName(), key.HashKey()).Index(gi.name).AllWithContext(ctx, items)
if err != nil {
if err == dynamo.ErrNotFound {
gi.log.info(ctx, key.TableName(), ErrNoItemFound.Error())
return false, nil
}
gi.log.error(ctx, key.TableName(), err.Error())
return false, err
}
val := reflect.ValueOf(items)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
if val.Kind() == reflect.Array || val.Kind() == reflect.Slice {
if val.Len() == 0 {
return false, nil
}
}
return true, nil
}
func (gi GlobalIndex) table(tableName string) dynamo.Table {
return gi.dynamoClient.Table(tableName)
}
// QueryWithContext by query; it accepts a query interface that is used to get the table name, hash key and range key with its operator if it exists;
// context which used to enable log with context, the output will be given in items
// returns error in case of error
func (gi GlobalIndex) QueryWithContext(ctx context.Context, query QueryInterface, item interface{}) error {
if !IsPointerOFSlice(item) {
return ErrInvalidPointerSliceType
}
if err := isValidKey(query); err != nil {
gi.log.error(ctx, query.TableName(), err.Error())
return err
}
q := gi.table(query.TableName()).Get(*query.HashKeyName(), query.HashKey()).Index(gi.name)
// by range
if query.RangeKeyName() != nil && query.RangeKey() != nil {
q = q.Range(*query.RangeKeyName(), dynamo.Operator(query.RangeOp()), query.RangeKey())
}
if limit := valueFromPtr(query.Limit()); limit > 0 {
q = q.Limit(limit)
}
if query.Descending() {
q = q.Order(dynamo.Descending)
}
err := q.AllWithContext(ctx, item)
if err != nil {
gi.log.error(ctx, query.TableName(), err.Error())
return err
}
return nil
}
// Query by query; it accepts a query interface that is used to get the table name, hash key and range key with its operator if it exists;
// returns error in case of error
func (gi GlobalIndex) Query(query QueryInterface, item interface{}) error {
return gi.QueryWithContext(context.TODO(), query, item)
}