forked from go-kivik/kivik
-
Notifications
You must be signed in to change notification settings - Fork 0
/
changes.go
124 lines (105 loc) · 3.87 KB
/
changes.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
package kivik
import (
"context"
"github.com/IG-Soft/kivik/v3/driver"
)
// Changes is an iterator over the database changes feed.
type Changes struct {
*iter
changesi driver.Changes
}
// Next prepares the next result value for reading. It returns true on success
// or false if there are no more results, due to an error or the changes feed
// having been closed. Err should be consulted to determine any error.
func (c *Changes) Next() bool {
return c.iter.Next()
}
// Err returns the error, if any, that was encountered during iteration. Err may
// be called after an explicit or implicit Close.
func (c *Changes) Err() error {
return c.iter.Err()
}
// Close closes the Changes feed, preventing further enumeration, and freeing
// any resources (such as the http request body) of the underlying query. If
// Next is called and there are no further results, Changes is closed
// automatically and it will suffice to check the result of Err. Close is
// idempotent and does not affect the result of Err.
func (c *Changes) Close() error {
return c.iter.Close()
}
type changesIterator struct{ driver.Changes }
var _ iterator = &changesIterator{}
func (c *changesIterator) Next(i interface{}) error { return c.Changes.Next(i.(*driver.Change)) }
func newChanges(ctx context.Context, changesi driver.Changes) *Changes {
return &Changes{
iter: newIterator(ctx, &changesIterator{changesi}, &driver.Change{}),
changesi: changesi,
}
}
// Changes returns a list of changed revs.
func (c *Changes) Changes() []string {
return c.curVal.(*driver.Change).Changes
}
// Deleted returns true if the change relates to a deleted document.
func (c *Changes) Deleted() bool {
return c.curVal.(*driver.Change).Deleted
}
// ID returns the ID of the current result.
func (c *Changes) ID() string {
return c.curVal.(*driver.Change).ID
}
// ScanDoc works the same as ScanValue, but on the doc field of the result. It
// is only valid for results that include documents.
func (c *Changes) ScanDoc(dest interface{}) error {
runlock, err := c.rlock()
if err != nil {
return err
}
defer runlock()
return scan(dest, c.curVal.(*driver.Change).Doc)
}
// Changes returns an iterator over the real-time changes feed. The feed remains
// open until explicitly closed, or an error is encountered.
// See http://couchdb.readthedocs.io/en/latest/api/database/changes.html#get--db-_changes
func (db *DB) Changes(ctx context.Context, options ...Options) (*Changes, error) {
changesi, err := db.driverDB.Changes(ctx, mergeOptions(options...))
if err != nil {
return nil, err
}
return newChanges(ctx, changesi), nil
}
// Seq returns the Seq of the current result.
func (c *Changes) Seq() string {
return c.curVal.(*driver.Change).Seq
}
// LastSeq returns the last update sequence id present in the change set,
// if returned by the server. This value is only guaranteed to be set after
// all changes have been enumerated through by Next, thus should only be
// read after processing all changes in a change set. Calling Close before
// enumerating will render this value unreliable.
func (c *Changes) LastSeq() string {
if c.changesi == nil {
return ""
}
return c.changesi.LastSeq()
}
// Pending returns the count of remaining items in the change feed. This
// value is only guaranteed to be set after all changes have been
// enumerated through by Next, thus should only be read after processing all
// changes in a change set. Calling Close before enumerating will render
// this value unreliable.
func (c *Changes) Pending() int64 {
if c.changesi == nil {
return 0
}
return c.changesi.Pending()
}
// ETag returns the unquoted ETag header, if any. Unlike LastSeq and Pending,
// because this value is returned in the response header (for standard CouchDB
// operation) anyway, it can be read immediately, before iteration even begins.
func (c *Changes) ETag() string {
if c.changesi == nil {
return ""
}
return c.changesi.ETag()
}