-
Notifications
You must be signed in to change notification settings - Fork 1
/
iter.go
91 lines (74 loc) · 2.24 KB
/
iter.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
package dynamodb
import (
"fmt"
"github.com/ace-teknologi/memzy"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)
var (
// ErrNullClient is returned if you try to create an iterator with a null client
ErrNullClient = fmt.Errorf("Cannot create an Iter with a null client")
)
// Iter provides a convenient interface for iterating over the elements returned
// from paginated list API calls. Successive calls to the Next method will step
// through each item in the list, fetching pages of items as needed. Iterators
// are not thread-safe, so they should not be consumed across multiple
// goroutines.
type Iter struct {
c *Client
cur map[string]*dynamodb.AttributeValue
err error
nextStartKey map[string]*dynamodb.AttributeValue
values []map[string]*dynamodb.AttributeValue
}
// NewIter returns a pointer to an Iter. It also performs an initial scan so it
// is ready to go, this probably should be avoided.
func (c *Client) NewIter(args ...interface{}) memzy.Iter {
// Ensure we didn't get a null client
if c == nil {
return &Iter{
err: ErrNullClient,
}
}
it := &Iter{c: c}
it.getNextPage()
return it
}
// Current returns the most recent item visited by a call to Next.
func (it *Iter) Current(v interface{}) error {
return dynamodbattribute.UnmarshalMap(it.cur, v)
}
// Err returns the error, if any, that caused the Iter to stop. It must be
// inspected after Next returns false.
func (it *Iter) Err() error {
return it.err
}
// Next advances the Iter to the next item in the list, which will then be
// available through the Current method. It returns false when the iterator
// stops at the end of the list.
func (it *Iter) Next() bool {
if len(it.values) == 0 && it.nextStartKey != nil {
// get more pages
it.getNextPage()
}
if len(it.values) == 0 {
// we are finished here
return false
}
it.cur = it.values[0]
it.values = it.values[1:]
return true
}
func (it *Iter) getNextPage() {
input := &dynamodb.ScanInput{
ExclusiveStartKey: it.nextStartKey,
TableName: it.c.TableName,
}
out, err := it.c.Service.Scan(input)
if err != nil {
it.err = err
return
}
it.nextStartKey = out.LastEvaluatedKey
it.values = out.Items
}