-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathcursor.go
159 lines (136 loc) · 2.67 KB
/
cursor.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
153
154
155
156
157
158
159
package aranGO
import (
"encoding/json"
"errors"
"reflect"
"time"
)
type Cursor struct {
db *Database `json:"-"`
Id string `json:"Id"`
Index int `json:"-"`
Result []interface{} `json:"result"`
More bool `json:"hasMore"`
Amount int `json:"count"`
Data Extra `json:"extra"`
Err bool `json:"error"`
ErrMsg string `json:"errorMessage"`
Code int `json:"code"`
max int
Time time.Duration `json:"time"`
}
func NewCursor(db *Database) *Cursor {
var c Cursor
if db == nil {
return nil
}
c.db = db
return &c
}
// Delete cursor in server and free RAM
func (c *Cursor) Delete() error {
if c.Id == "" {
return errors.New("Invalid cursor to delete")
}
res, err := c.db.send("cursor", c.Id, "DELETE", nil, c, c)
if err != nil {
return nil
}
switch res.Status() {
case 202:
return nil
case 404:
return errors.New("Cursor does not exist")
default:
return nil
}
}
func (c *Cursor) FetchBatch(r interface{}) error {
kind := reflect.ValueOf(r).Elem().Kind()
if kind != reflect.Slice && kind != reflect.Array {
return errors.New("Container must be Slice of array kind")
}
b, err := json.Marshal(c.Result)
if err != nil {
return err
}
err = json.Unmarshal(b, r)
if err != nil {
return err
}
// fetch next batch
if c.HasMore() {
res, err := c.db.send("cursor", c.Id, "PUT", nil, c, c)
if res.Status() == 200 {
return nil
}
if err != nil {
return err
}
}
return nil
}
// FetchOne iterates over cursor, returns false when no more values into batch, fetch next batch if necesary.
func (c *Cursor) FetchOne(r interface{}) bool {
if c.Index > c.max {
if c.More {
//fetch rest from server
res, err := c.db.send("cursor", c.Id, "PUT", nil, c, c)
if err != nil {
return false
}
if res.Status() == 200 {
c.Index = 0
return true
} else {
return false
}
} else {
// last doc
return false
}
} else {
b, err := json.Marshal(c.Result[c.Index])
err = json.Unmarshal(b, r)
c.Index++ // move to next value into result
if err != nil {
return false
} else {
return true
}
}
}
// move cursor index by 1
func (c *Cursor) Next(r interface{}) bool {
if c.Index == c.max {
return false
} else {
c.Index++
if c.Index == c.max {
return true
} else {
return false
}
}
}
type Extra struct {
Stats Stats `json:"stats"`
}
type Stats struct {
FullCount int `json:"fullCount"`
}
func (c Cursor) Count() int {
return c.Amount
}
func (c *Cursor) FullCount() int {
return c.Data.Stats.FullCount
}
func (c Cursor) HasMore() bool {
return c.More
}
func (c Cursor) Error() bool {
return c.Err
}
func (c Cursor) ErrCode() int {
return c.Code
}