-
Notifications
You must be signed in to change notification settings - Fork 104
/
Copy pathcollection_rangescan.go
149 lines (124 loc) · 3.99 KB
/
collection_rangescan.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
package gocb
import (
"context"
"time"
"github.com/couchbase/gocbcore/v10"
)
// ScanOptions are the set of options available to the Scan operation.
type ScanOptions struct {
Transcoder Transcoder
Timeout time.Duration
ParentSpan RequestSpan
// Using a deadlined Context alongside a Timeout will cause the shorter of the two to cause cancellation, this
// also applies to global level timeouts.
// UNCOMMITTED: This API may change in the future.
Context context.Context
IDsOnly bool
ConsistentWith *MutationState
// BatchByteLimit specifies a limit to how many bytes are sent from server to client on each partition batch.
// Defaults to 15000. A value of 0 is equivalent to no limit.
BatchByteLimit *uint32
// BatchItemLimit specifies a limit to how many items are sent from server to client on each partition batch.
// Defaults to 50. A value of 0 is equivalent to no limit.
BatchItemLimit *uint32
// Concurrency specifies the maximum number of scans that can be active at the same time.
// Defaults to 1. Care must be taken to ensure that the server does not run out of resources due to concurrent scans.
//
// # UNCOMMITTED
//
// This API is UNCOMMITTED and may change in the future.
Concurrency uint16
// Internal: This should never be used and is not supported.
Internal struct {
User string
}
}
// ScanTerm represents a term that can be used during a Scan operation.
type ScanTerm struct {
Term string
Exclusive bool
}
// ScanTermMinimum represents the minimum value that a ScanTerm can represent.
func ScanTermMinimum() *ScanTerm {
return &ScanTerm{
Term: "\x00",
}
}
// ScanTermMaximum represents the maximum value that a ScanTerm can represent.
func ScanTermMaximum() *ScanTerm {
return &ScanTerm{
Term: "\xf48fbfbf",
}
}
// ScanType represents the mode of execution to use for a Scan operation.
type ScanType interface {
isScanType()
}
// NewRangeScanForPrefix creates a new range scan for the given prefix, starting at the prefix and ending at the prefix
// plus maximum.
func NewRangeScanForPrefix(prefix string) RangeScan {
return RangeScan{
From: &ScanTerm{
Term: prefix,
},
To: &ScanTerm{
Term: prefix + ScanTermMaximum().Term,
},
}
}
// RangeScan indicates that the Scan operation should scan a range of keys.
type RangeScan struct {
From *ScanTerm
To *ScanTerm
}
func (rs RangeScan) isScanType() {}
func (rs RangeScan) toCore() (*gocbcore.RangeScanCreateRangeScanConfig, error) {
to := rs.To
from := rs.From
rangeOptions := &gocbcore.RangeScanCreateRangeScanConfig{}
if from != nil {
if from.Exclusive {
rangeOptions.ExclusiveStart = []byte(from.Term)
} else {
rangeOptions.Start = []byte(from.Term)
}
}
if to != nil {
if to.Exclusive {
rangeOptions.ExclusiveEnd = []byte(to.Term)
} else {
rangeOptions.End = []byte(to.Term)
}
}
return rangeOptions, nil
}
// SamplingScan indicates that the Scan operation should perform random sampling.
type SamplingScan struct {
Limit uint64
Seed uint64
}
func (rs SamplingScan) isScanType() {}
func (rs SamplingScan) toCore() (*gocbcore.RangeScanCreateRandomSamplingConfig, error) {
if rs.Limit == 0 {
return nil, makeInvalidArgumentsError("sampling scan limit must be greater than 0")
}
return &gocbcore.RangeScanCreateRandomSamplingConfig{
Samples: rs.Limit,
Seed: rs.Seed,
}, nil
}
// Scan performs a scan across a Collection, returning a stream of documents.
// Use this API for low concurrency batch queries where latency is not critical as the system may have to scan
// a lot of documents to find the matching documents.
// For low latency range queries, it is recommended that you use SQL++ with the necessary indexes.
func (c *Collection) Scan(scanType ScanType, opts *ScanOptions) (*ScanResult, error) {
return autoOpControl(c.kvController(), "range_scan", func(agent kvProvider) (*ScanResult, error) {
if opts == nil {
opts = &ScanOptions{}
}
if opts.Timeout == 0 {
opts.Timeout = c.timeoutsConfig.KVScanTimeout
}
return agent.Scan(c, scanType, opts)
})
}