-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Support specifying MaxBytes in range request
#14810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3ccba17
55d9c12
1c0986a
25b2a28
0c3aef1
97d4b6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,22 +125,20 @@ func Range(ctx context.Context, lg *zap.Logger, kv mvcc.KV, txnRead mvcc.TxnRead | |
| defer txnRead.End() | ||
| } | ||
|
|
||
| limit := r.Limit | ||
| limit, maxBytes := r.Limit, r.MaxBytes | ||
| if r.SortOrder != pb.RangeRequest_NONE || | ||
| r.MinModRevision != 0 || r.MaxModRevision != 0 || | ||
| r.MinCreateRevision != 0 || r.MaxCreateRevision != 0 { | ||
| // fetch everything; sort and truncate afterwards | ||
| limit = 0 | ||
| } | ||
| if limit > 0 { | ||
| // fetch one extra for 'more' flag | ||
| limit = limit + 1 | ||
| maxBytes = 0 | ||
| } | ||
|
|
||
| ro := mvcc.RangeOptions{ | ||
| Limit: limit, | ||
| Rev: r.Revision, | ||
| Count: r.CountOnly, | ||
| Limit: limit, | ||
| MaxBytes: maxBytes, | ||
| Rev: r.Revision, | ||
| Count: r.CountOnly, | ||
| } | ||
|
|
||
| rr, err := txnRead.Range(ctx, r.Key, mkGteRange(r.RangeEnd), ro) | ||
|
|
@@ -201,10 +199,23 @@ func Range(ctx context.Context, lg *zap.Logger, kv mvcc.KV, txnRead mvcc.TxnRead | |
| } | ||
| } | ||
|
|
||
| resp.More = rr.More | ||
| if r.Limit > 0 && len(rr.KVs) > int(r.Limit) { | ||
| rr.KVs = rr.KVs[:r.Limit] | ||
| resp.More = true | ||
| } | ||
| if r.MaxBytes > 0 && maxBytes == 0 { | ||
| var totalBytes int64 | ||
| for i, kv := range rr.KVs { | ||
| totalBytes += int64(kv.Size()) | ||
| if totalBytes > r.MaxBytes { | ||
| resp.More = true | ||
| rr.KVs = rr.KVs[:i] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand the code correctly, it means we might be sending '0' items, it is, we might stuck completely, I think we should prioritize giving at least 1 item in such situation. And be very explicit that in this situation the maxBytes contract can be exceeded. We also need to have tests for this.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you understood correctly. The initial version was to return the result with size just exceeding the Given the max object size is 1.5MB, we can warm users the maxBytes should be bigger than 1.5MB to avoid returning 0 items. WDYT? |
||
| break | ||
| } | ||
| } | ||
| } | ||
|
|
||
| trace.Step("filter and sort the key-value pairs") | ||
| resp.Header.Revision = rr.Rev | ||
| resp.Count = int64(rr.Count) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -87,12 +87,13 @@ func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev i | |
| } | ||
|
|
||
| limit := int(ro.Limit) | ||
| if limit <= 0 || limit > len(revpairs) { | ||
| if limit <= 0 || limit >= len(revpairs) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is no-op |
||
| limit = len(revpairs) | ||
| } | ||
|
|
||
| kvs := make([]mvccpb.KeyValue, limit) | ||
| revBytes := newRevBytes() | ||
| var totalBytes int64 | ||
| for i, revpair := range revpairs[:len(kvs)] { | ||
| select { | ||
| case <-ctx.Done(): | ||
|
|
@@ -115,6 +116,11 @@ func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev i | |
| zap.Int("len-values", len(vs)), | ||
| ) | ||
| } | ||
| totalBytes += int64(len(vs[0])) | ||
| if ro.MaxBytes > 0 && totalBytes > ro.MaxBytes { | ||
| kvs = kvs[:i] | ||
| break | ||
| } | ||
| if err := kvs[i].Unmarshal(vs[0]); err != nil { | ||
| tr.s.lg.Fatal( | ||
| "failed to unmarshal mvccpb.KeyValue", | ||
|
|
@@ -123,7 +129,7 @@ func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev i | |
| } | ||
| } | ||
| tr.trace.Step("range keys from bolt db") | ||
| return &RangeResult{KVs: kvs, Count: total, Rev: curRev}, nil | ||
| return &RangeResult{KVs: kvs, Count: total, Rev: curRev, More: total > len(kvs)}, nil | ||
linxiulei marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| func (tr *storeTxnRead) End() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.