diff --git a/api/storeapi/store_api.proto b/api/storeapi/store_api.proto index 8d34fc23..dcf87dee 100644 --- a/api/storeapi/store_api.proto +++ b/api/storeapi/store_api.proto @@ -254,6 +254,9 @@ message FetchRequest { bool explain = 3; repeated IdWithHint ids_with_hints = 4; FieldsFilter fields_filter = 5; + // if true, skip masks will be evaluated + // set to false in fetch after search since ids are already skipped + bool evalSkipMasks = 6; } message StatusRequest {} diff --git a/frac/active.go b/frac/active.go index 7c3691c1..d5f827d6 100644 --- a/frac/active.go +++ b/frac/active.go @@ -369,7 +369,7 @@ func (f *Active) String() string { return fracToString(f, "active") } -func (f *Active) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { +func (f *Active) Fetch(ctx context.Context, ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { if f.Info().DocsTotal == 0 { // it is empty active fraction state return nil, nil } @@ -377,7 +377,7 @@ func (f *Active) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { dp := f.createDataProvider(ctx) defer dp.release() - return dp.Fetch(ids) + return dp.Fetch(ids, evalSkipMasks) } func (f *Active) Search(ctx context.Context, params processor.SearchParams) (*seq.QPR, error) { diff --git a/frac/active_index.go b/frac/active_index.go index 27e4e464..22931d4d 100644 --- a/frac/active_index.go +++ b/frac/active_index.go @@ -68,7 +68,7 @@ func (dp *activeDataProvider) getTokenIndex() *activeTokenIndex { } } -func (dp *activeDataProvider) Fetch(ids []seq.ID) ([][]byte, error) { +func (dp *activeDataProvider) Fetch(ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { sw := stopwatch.New() defer sw.Export( @@ -88,7 +88,7 @@ func (dp *activeDataProvider) Fetch(ids []seq.ID) ([][]byte, error) { }} for _, fi := range indexes { - if err := processor.IndexFetch(ids, sw, &fi, res); err != nil { + if err := processor.IndexFetch(ids, evalSkipMasks, sw, &fi, res); err != nil { return nil, err } } @@ -271,12 +271,16 @@ func (di *activeFetchIndex) GetBlocksOffsets(num uint32) uint64 { return di.blocksOffsets[num] } -func (di *activeFetchIndex) GetDocPos(ids []seq.ID) ([]seq.DocPos, error) { +func (di *activeFetchIndex) GetDocPos(ids []seq.ID, evalSkipMasks bool) ([]seq.DocPos, error) { docsPos := make([]seq.DocPos, len(ids)) for i, id := range ids { docsPos[i] = di.docsPositions.GetSync(id) } + if !evalSkipMasks { + return docsPos, nil + } + minLID, maxLID := uint32(0), uint32(math.MaxUint32) skipLIDsIterator, has, err := di.skipMaskProvider.GetIDsIteratorByFrac(di.fracName, minLID, maxLID, false) if err != nil { diff --git a/frac/fraction.go b/frac/fraction.go index a3027c97..942f3963 100644 --- a/frac/fraction.go +++ b/frac/fraction.go @@ -19,7 +19,7 @@ type Fraction interface { Info() *common.Info IsIntersecting(from seq.MID, to seq.MID) bool Contains(mid seq.MID) bool - Fetch(context.Context, []seq.ID) ([][]byte, error) + Fetch(context.Context, []seq.ID, bool) ([][]byte, error) Search(context.Context, processor.SearchParams) (*seq.QPR, error) FindLIDs(context.Context, []seq.ID) ([]seq.LID, error) } diff --git a/frac/fraction_concurrency_test.go b/frac/fraction_concurrency_test.go index a5c19b22..9f104700 100644 --- a/frac/fraction_concurrency_test.go +++ b/frac/fraction_concurrency_test.go @@ -231,7 +231,7 @@ func readTest(t *testing.T, fraction Fraction, numReaders, numQueries int, docs return fmt.Errorf("search failed: %w", err) } - fetchedResult, err := fraction.Fetch(ctx, qpr.IDs.IDs()) + fetchedResult, err := fraction.Fetch(ctx, qpr.IDs.IDs(), false) if err != nil { return fmt.Errorf("fetch failed: %w", err) } diff --git a/frac/fraction_test.go b/frac/fraction_test.go index ec5f3d85..094963bc 100644 --- a/frac/fraction_test.go +++ b/frac/fraction_test.go @@ -1656,7 +1656,7 @@ func (s *FractionTestSuite) TestSearchLargeFrac() { qprIDs := qpr.IDs.IDs() totalIDsScrolled += len(qprIDs) - docs, err := s.fraction.Fetch(context.Background(), qprIDs) + docs, err := s.fraction.Fetch(context.Background(), qprIDs, false) s.Require().NoError(err, "fetch failed for order=%v", order) for j, doc := range docs { @@ -1965,7 +1965,7 @@ func (s *FractionTestSuite) AssertSearchWithSearchParams( s.Require().NoError(err, "search failed for query with order=%v", order) s.Require().Equal(len(expectedIndexes), qpr.IDs.Len(), "doc count doesn't match") - docs, err := s.fraction.Fetch(context.Background(), qpr.IDs.IDs()) + docs, err := s.fraction.Fetch(context.Background(), qpr.IDs.IDs(), false) s.Require().NoError(err, "failed to fetch docs") if order.IsReverse() { diff --git a/frac/processor/fetch.go b/frac/processor/fetch.go index e2267780..4fea8930 100644 --- a/frac/processor/fetch.go +++ b/frac/processor/fetch.go @@ -7,13 +7,13 @@ import ( type fetchIndex interface { GetBlocksOffsets(uint32) uint64 - GetDocPos([]seq.ID) ([]seq.DocPos, error) + GetDocPos([]seq.ID, bool) ([]seq.DocPos, error) ReadDocs(blockOffset uint64, docOffsets []uint64) ([][]byte, error) } -func IndexFetch(ids []seq.ID, sw *stopwatch.Stopwatch, fetchIndex fetchIndex, res [][]byte) error { +func IndexFetch(ids []seq.ID, evalSkipMasks bool, sw *stopwatch.Stopwatch, fetchIndex fetchIndex, res [][]byte) error { m := sw.Start("get_docs_pos") - docsPos, err := fetchIndex.GetDocPos(ids) + docsPos, err := fetchIndex.GetDocPos(ids, evalSkipMasks) if err != nil { return err } diff --git a/frac/remote.go b/frac/remote.go index 7658e80e..cf12e871 100644 --- a/frac/remote.go +++ b/frac/remote.go @@ -116,14 +116,14 @@ func (f *Remote) Contains(mid seq.MID) bool { return f.info.IsIntersecting(mid, mid) } -func (f *Remote) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { +func (f *Remote) Fetch(ctx context.Context, ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { dp, err := f.createDataProvider(ctx) if err != nil { return nil, err } defer dp.release() - return dp.Fetch(ids) + return dp.Fetch(ids, evalSkipMasks) } func (f *Remote) Search(ctx context.Context, params processor.SearchParams) (*seq.QPR, error) { diff --git a/frac/sealed.go b/frac/sealed.go index bda4fc72..282ea8eb 100644 --- a/frac/sealed.go +++ b/frac/sealed.go @@ -308,11 +308,11 @@ func (f *Sealed) String() string { return fracToString(f, "sealed") } -func (f *Sealed) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { +func (f *Sealed) Fetch(ctx context.Context, ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { dp := f.createDataProvider(ctx) defer dp.release() - return dp.Fetch(ids) + return dp.Fetch(ids, evalSkipMasks) } func (f *Sealed) Search(ctx context.Context, params processor.SearchParams) (*seq.QPR, error) { diff --git a/frac/sealed_index.go b/frac/sealed_index.go index 7c62713c..f32ad4f9 100644 --- a/frac/sealed_index.go +++ b/frac/sealed_index.go @@ -91,7 +91,7 @@ func (dp *sealedDataProvider) release() { dp.idsProvider.Release() } -func (dp *sealedDataProvider) Fetch(ids []seq.ID) ([][]byte, error) { +func (dp *sealedDataProvider) Fetch(ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { sw := stopwatch.New() defer sw.Export( @@ -100,7 +100,7 @@ func (dp *sealedDataProvider) Fetch(ids []seq.ID) ([][]byte, error) { ) res := make([][]byte, len(ids)) - if err := processor.IndexFetch(ids, sw, dp.getFetchIndex(), res); err != nil { + if err := processor.IndexFetch(ids, evalSkipMasks, sw, dp.getFetchIndex(), res); err != nil { return nil, err } @@ -280,9 +280,13 @@ func (fi *sealedFetchIndex) GetBlocksOffsets(num uint32) uint64 { return fi.blocksOffsets[num] } -func (fi *sealedFetchIndex) GetDocPos(ids []seq.ID) ([]seq.DocPos, error) { +func (fi *sealedFetchIndex) GetDocPos(ids []seq.ID, evalSkipMasks bool) ([]seq.DocPos, error) { allLids := fi.findLIDs(ids) + if !evalSkipMasks { + return fi.getDocPosByLIDs(allLids), nil + } + minLID, maxLID := uint32(0), uint32(math.MaxUint32) if len(allLids) > 0 { // allLids can be not sorted diff --git a/fracmanager/fetcher.go b/fracmanager/fetcher.go index 4df1b223..984f5e0e 100644 --- a/fracmanager/fetcher.go +++ b/fracmanager/fetcher.go @@ -29,7 +29,7 @@ func NewFetcher(maxWorkersNum int) *Fetcher { } } -func (f *Fetcher) FetchDocs(ctx context.Context, fracs List, ids []seq.IDSource) ([][]byte, error) { +func (f *Fetcher) FetchDocs(ctx context.Context, fracs List, ids []seq.IDSource, evalSkipMasks bool) ([][]byte, error) { sw := stopwatch.New() m := sw.Start("fill_revers_pos") @@ -44,7 +44,7 @@ func (f *Fetcher) FetchDocs(ctx context.Context, fracs List, ids []seq.IDSource) m.Stop() m = sw.Start("fetch_async") - docsByFracs, err := f.fetchDocsAsync(ctx, fracs, idsByFrac) + docsByFracs, err := f.fetchDocsAsync(ctx, fracs, idsByFrac, evalSkipMasks) m.Stop() // arrange the result in the original order of ids @@ -64,7 +64,7 @@ func (f *Fetcher) FetchDocs(ctx context.Context, fracs List, ids []seq.IDSource) return result, err } -func (f *Fetcher) fetchDocsAsync(ctx context.Context, fracs []frac.Fraction, idsByFrac [][]seq.ID) ([][][]byte, error) { +func (f *Fetcher) fetchDocsAsync(ctx context.Context, fracs []frac.Fraction, idsByFrac [][]seq.ID, evalSkipMasks bool) ([][][]byte, error) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -84,7 +84,7 @@ loop: wg.Add(1) go func() { var fracErr error - if docs[i], fracErr = fracFetch(ctx, frac, idsByFrac[i]); fracErr != nil { + if docs[i], fracErr = fracFetch(ctx, frac, idsByFrac[i], evalSkipMasks); fracErr != nil { once.Do(func() { err = fracErr cancel() @@ -105,13 +105,13 @@ loop: return docs, nil } -func fracFetch(ctx context.Context, f frac.Fraction, ids []seq.ID) (_ [][]byte, err error) { +func fracFetch(ctx context.Context, f frac.Fraction, ids []seq.ID, evalSkipMasks bool) (_ [][]byte, err error) { defer func() { if panicData := util.RecoverToError(recover(), metric.StorePanics); panicData != nil { err = fmt.Errorf("internal error: fetch panicked on fraction %s, error=%w", f.Info().Name(), panicData) } }() - return f.Fetch(ctx, ids) + return f.Fetch(ctx, ids, evalSkipMasks) } func sortIDs(idsOrig seq.IDSources) (seq.IDSources, seq.MID, seq.MID) { diff --git a/fracmanager/fetcher_test.go b/fracmanager/fetcher_test.go index 1328b8ad..85e642c3 100644 --- a/fracmanager/fetcher_test.go +++ b/fracmanager/fetcher_test.go @@ -31,7 +31,7 @@ func TestFetcher_ShouldFetchMultiFrac(t *testing.T) { {ID: seq.SimpleID(30)}, } - docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs) + docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs, false) assert.NoError(t, err) assert.Equal(t, [][]byte{[]byte("doc1"), []byte("doc2"), []byte("doc4"), []byte("doc3")}, docs) @@ -51,7 +51,7 @@ func TestFetcher_DocNotFound(t *testing.T) { {ID: seq.SimpleID(20)}, } - docs, err := fetcher.FetchDocs(context.Background(), List{frac1}, fetchIDs) + docs, err := fetcher.FetchDocs(context.Background(), List{frac1}, fetchIDs, false) assert.NoError(t, err) assert.Len(t, docs, 2) @@ -82,7 +82,7 @@ func TestFetcher_ShouldUseHints(t *testing.T) { {ID: seq.SimpleID(10), Hint: frac1.Info().Name()}, } - docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs) + docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs, false) assert.NoError(t, err) assert.Equal(t, [][]byte{[]byte("apple"), []byte("pineapple"), []byte("orange")}, docs) @@ -115,7 +115,7 @@ func TestFetcher_ShouldUseHints_MixedScenario(t *testing.T) { {ID: seq.SimpleID(50)}, } - docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs) + docs, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2, frac3}, fetchIDs, false) assert.NoError(t, err) assert.Equal(t, [][]byte{[]byte("apple"), []byte("pineapple"), []byte("orange"), []byte("mango")}, docs) @@ -148,7 +148,7 @@ func TestFetcher_OutOfRangeFractions(t *testing.T) { {ID: seq.SimpleID(20)}, } - docs, err := fetcher.FetchDocs(context.Background(), List{frac1}, fetchIDs) + docs, err := fetcher.FetchDocs(context.Background(), List{frac1}, fetchIDs, false) assert.NoError(t, err) assert.Equal(t, [][]byte{[]byte("apple"), nil, []byte("banana"), nil}, docs) @@ -170,7 +170,7 @@ func TestFetcher_FetchError(t *testing.T) { fetchIDs := []seq.IDSource{{ID: seq.SimpleID(20)}} - _, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2}, fetchIDs) + _, err := fetcher.FetchDocs(context.Background(), List{frac1, frac2}, fetchIDs, false) assert.ErrorContains(t, err, "fetch failed") } @@ -199,7 +199,7 @@ func TestFetcher_ContextCancellation(t *testing.T) { {ID: seq.SimpleID(20)}, } - _, err := fetcher.FetchDocs(ctx, List{frac1, frac2, frac3, frac4}, ids) + _, err := fetcher.FetchDocs(ctx, List{frac1, frac2, frac3, frac4}, ids, false) assert.Error(t, err) assert.ErrorIs(t, context.Canceled, err) diff --git a/fracmanager/proxy_frac.go b/fracmanager/proxy_frac.go index 6d4df41f..480e41d7 100644 --- a/fracmanager/proxy_frac.go +++ b/fracmanager/proxy_frac.go @@ -58,10 +58,10 @@ func (p *fractionProxy) Contains(mid seq.MID) bool { return p.impl.Contains(mid) } -func (p *fractionProxy) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { +func (p *fractionProxy) Fetch(ctx context.Context, ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { p.mu.RLock() defer p.mu.RUnlock() - return p.impl.Fetch(ctx, ids) + return p.impl.Fetch(ctx, ids, evalSkipMasks) } func (p *fractionProxy) Search(ctx context.Context, params processor.SearchParams) (*seq.QPR, error) { @@ -187,7 +187,7 @@ func (emptyFraction) Contains(mid seq.MID) bool { return false } -func (emptyFraction) Fetch(ctx context.Context, ids []seq.ID) ([][]byte, error) { +func (emptyFraction) Fetch(ctx context.Context, ids []seq.ID, evalSkipMasks bool) ([][]byte, error) { return nil, nil } diff --git a/fracmanager/searcher_test.go b/fracmanager/searcher_test.go index bdb07ec6..88277b18 100644 --- a/fracmanager/searcher_test.go +++ b/fracmanager/searcher_test.go @@ -40,7 +40,7 @@ func (f *testFakeFrac) Contains(mid seq.MID) bool { return f.info.IsIntersecting(mid, mid) } -func (f *testFakeFrac) Fetch(_ context.Context, ids []seq.ID) ([][]byte, error) { +func (f *testFakeFrac) Fetch(_ context.Context, ids []seq.ID, _ bool) ([][]byte, error) { f.fetchCount++ if f.fetchError != nil { return nil, f.fetchError diff --git a/pkg/storeapi/store_api.pb.go b/pkg/storeapi/store_api.pb.go index 8fbb52c1..f5db34cc 100644 --- a/pkg/storeapi/store_api.pb.go +++ b/pkg/storeapi/store_api.pb.go @@ -1593,11 +1593,14 @@ func (x *IdWithHint) GetHint() string { } type FetchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` - Explain bool `protobuf:"varint,3,opt,name=explain,proto3" json:"explain,omitempty"` - IdsWithHints []*IdWithHint `protobuf:"bytes,4,rep,name=ids_with_hints,json=idsWithHints,proto3" json:"ids_with_hints,omitempty"` - FieldsFilter *FetchRequest_FieldsFilter `protobuf:"bytes,5,opt,name=fields_filter,json=fieldsFilter,proto3" json:"fields_filter,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` + Explain bool `protobuf:"varint,3,opt,name=explain,proto3" json:"explain,omitempty"` + IdsWithHints []*IdWithHint `protobuf:"bytes,4,rep,name=ids_with_hints,json=idsWithHints,proto3" json:"ids_with_hints,omitempty"` + FieldsFilter *FetchRequest_FieldsFilter `protobuf:"bytes,5,opt,name=fields_filter,json=fieldsFilter,proto3" json:"fields_filter,omitempty"` + // if true, skip masks will be evaluated + // set to false in fetch after search since ids are already skipped + EvalSkipMasks bool `protobuf:"varint,6,opt,name=evalSkipMasks,proto3" json:"evalSkipMasks,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1660,6 +1663,13 @@ func (x *FetchRequest) GetFieldsFilter() *FetchRequest_FieldsFilter { return nil } +func (x *FetchRequest) GetEvalSkipMasks() bool { + if x != nil { + return x.EvalSkipMasks + } + return false +} + type StatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -2421,7 +2431,7 @@ var file_storeapi_store_api_proto_rawDesc = string([]byte{ 0x63, 0x65, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x22, 0x30, 0x0a, 0x0a, 0x49, 0x64, 0x57, 0x69, 0x74, 0x68, 0x48, 0x69, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x0c, 0x46, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x0c, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, @@ -2433,100 +2443,102 @@ var file_storeapi_store_api_proto_rawDesc = string([]byte{ 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x1a, 0x45, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4d, 0x0a, 0x0e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, - 0x0b, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, - 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0xac, 0x01, 0x0a, 0x07, 0x41, - 0x67, 0x67, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, - 0x4e, 0x43, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, - 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x53, 0x55, 0x4d, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, - 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x10, - 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x4d, 0x41, 0x58, 0x10, 0x03, - 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x41, 0x56, 0x47, - 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x51, - 0x55, 0x41, 0x4e, 0x54, 0x49, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x47, - 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x10, 0x06, 0x12, 0x19, - 0x0a, 0x15, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, - 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x07, 0x2a, 0x26, 0x0a, 0x05, 0x4f, 0x72, 0x64, - 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x53, 0x43, - 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x53, 0x43, 0x10, - 0x01, 0x2a, 0xe8, 0x01, 0x0a, 0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x47, 0x45, 0x53, 0x54, 0x4f, 0x52, 0x5f, - 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x57, 0x41, 0x4e, 0x54, 0x53, 0x5f, 0x4f, 0x4c, 0x44, 0x5f, - 0x44, 0x41, 0x54, 0x41, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, - 0x4e, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x48, 0x49, 0x54, - 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, - 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x04, 0x12, 0x19, 0x0a, - 0x15, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, - 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x54, 0x4f, 0x4f, 0x5f, - 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x4f, - 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, - 0x4e, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x53, 0x10, - 0x07, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x49, 0x4d, 0x49, - 0x54, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x08, 0x2a, 0x8a, 0x01, 0x0a, - 0x11, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x1d, - 0x0a, 0x19, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x03, 0x32, 0x9c, 0x05, 0x0a, 0x08, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x12, 0x32, 0x0a, 0x04, 0x42, 0x75, 0x6c, 0x6b, 0x12, 0x10, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x51, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, - 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x73, 0x79, - 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x63, 0x0a, 0x16, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, - 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x22, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, - 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, - 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, + 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x76, 0x61, 0x6c, 0x53, 0x6b, 0x69, 0x70, 0x4d, + 0x61, 0x73, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x76, 0x61, 0x6c, + 0x53, 0x6b, 0x69, 0x70, 0x4d, 0x61, 0x73, 0x6b, 0x73, 0x1a, 0x45, 0x0a, 0x0c, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x69, 0x73, 0x74, + 0x22, 0x0f, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x4d, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x2a, 0xac, 0x01, 0x0a, 0x07, 0x41, 0x67, 0x67, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x0e, + 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x00, + 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x53, 0x55, 0x4d, + 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x4d, + 0x49, 0x4e, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, + 0x5f, 0x4d, 0x41, 0x58, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, + 0x4e, 0x43, 0x5f, 0x41, 0x56, 0x47, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x47, 0x47, 0x5f, + 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x51, 0x55, 0x41, 0x4e, 0x54, 0x49, 0x4c, 0x45, 0x10, 0x05, 0x12, + 0x13, 0x0a, 0x0f, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x5f, 0x55, 0x4e, 0x49, 0x51, + 0x55, 0x45, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x47, 0x47, 0x5f, 0x46, 0x55, 0x4e, 0x43, + 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x07, 0x2a, + 0x26, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x52, 0x44, 0x45, + 0x52, 0x5f, 0x44, 0x45, 0x53, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x52, 0x44, 0x45, + 0x52, 0x5f, 0x41, 0x53, 0x43, 0x10, 0x01, 0x2a, 0xe8, 0x01, 0x0a, 0x0f, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, + 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x47, + 0x45, 0x53, 0x54, 0x4f, 0x52, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x57, 0x41, 0x4e, 0x54, + 0x53, 0x5f, 0x4f, 0x4c, 0x44, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, + 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x53, 0x5f, 0x48, 0x49, 0x54, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4f, 0x4f, 0x5f, + 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, + 0x53, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, + 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x05, 0x12, 0x1c, + 0x0a, 0x18, 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x53, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, + 0x54, 0x4f, 0x4f, 0x5f, 0x4d, 0x41, 0x4e, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x56, + 0x41, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x4f, 0x52, + 0x59, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, + 0x10, 0x08, 0x2a, 0x8a, 0x01, 0x0a, 0x11, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x73, 0x79, 0x6e, + 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x49, 0x6e, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x6f, + 0x6e, 0x65, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, + 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, + 0x64, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x03, 0x32, + 0x9c, 0x05, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x12, 0x32, 0x0a, 0x04, + 0x42, 0x75, 0x6c, 0x6b, 0x12, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, + 0x12, 0x33, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x73, + 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x16, 0x46, 0x65, 0x74, 0x63, + 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, + 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, + 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, + 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, - 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x05, 0x46, 0x65, 0x74, 0x63, 0x68, 0x12, 0x11, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x22, - 0x00, 0x30, 0x01, 0x12, 0x33, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x7a, 0x6f, 0x6e, 0x74, 0x65, 0x63, 0x68, 0x2f, - 0x73, 0x65, 0x71, 0x2d, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x61, 0x70, 0x69, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x14, 0x47, 0x65, 0x74, + 0x41, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x79, 0x6e, 0x63, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x05, 0x46, 0x65, 0x74, 0x63, + 0x68, 0x12, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x69, 0x6e, 0x61, 0x72, + 0x79, 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x30, 0x01, 0x12, 0x33, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x32, + 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x7a, 0x6f, + 0x6e, 0x74, 0x65, 0x63, 0x68, 0x2f, 0x73, 0x65, 0x71, 0x2d, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x61, 0x70, 0x69, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x61, + 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( diff --git a/pkg/storeapi/store_api_vtproto.pb.go b/pkg/storeapi/store_api_vtproto.pb.go index 199f99c9..4489b4be 100644 --- a/pkg/storeapi/store_api_vtproto.pb.go +++ b/pkg/storeapi/store_api_vtproto.pb.go @@ -648,6 +648,7 @@ func (m *FetchRequest) CloneVT() *FetchRequest { r := new(FetchRequest) r.Explain = m.Explain r.FieldsFilter = m.FieldsFilter.CloneVT() + r.EvalSkipMasks = m.EvalSkipMasks if rhs := m.Ids; rhs != nil { tmpContainer := make([]string, len(rhs)) copy(tmpContainer, rhs) @@ -1650,6 +1651,9 @@ func (this *FetchRequest) EqualVT(that *FetchRequest) bool { if !this.FieldsFilter.EqualVT(that.FieldsFilter) { return false } + if this.EvalSkipMasks != that.EvalSkipMasks { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -3785,6 +3789,16 @@ func (m *FetchRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.EvalSkipMasks { + i-- + if m.EvalSkipMasks { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if m.FieldsFilter != nil { size, err := m.FieldsFilter.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -5587,6 +5601,16 @@ func (m *FetchRequest) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.EvalSkipMasks { + i-- + if m.EvalSkipMasks { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } if m.FieldsFilter != nil { size, err := m.FieldsFilter.MarshalToSizedBufferVTStrict(dAtA[:i]) if err != nil { @@ -6399,6 +6423,9 @@ func (m *FetchRequest) SizeVT() (n int) { l = m.FieldsFilter.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.EvalSkipMasks { + n += 2 + } n += len(m.unknownFields) return n } @@ -11059,6 +11086,26 @@ func (m *FetchRequest) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EvalSkipMasks", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.EvalSkipMasks = bool(v != 0) default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -15947,6 +15994,26 @@ func (m *FetchRequest) UnmarshalVTUnsafe(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EvalSkipMasks", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.EvalSkipMasks = bool(v != 0) default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/proxy/search/async.go b/proxy/search/async.go index 74891830..f6b49c4a 100644 --- a/proxy/search/async.go +++ b/proxy/search/async.go @@ -316,7 +316,7 @@ func (si *Ingestor) FetchAsyncSearchResult( if size > 0 { fieldsFilter := tryParseFieldsFilter(pr.Request.Query) var err error - docsStream, err = si.FetchDocsStream(ctx, pr.QPR.IDs, false, fieldsFilter) + docsStream, err = si.FetchDocsStream(ctx, pr.QPR.IDs, false, true, fieldsFilter) if err != nil { return pr, nil, err } diff --git a/proxy/search/ingestor.go b/proxy/search/ingestor.go index 8d8c2ce4..d154a44a 100644 --- a/proxy/search/ingestor.go +++ b/proxy/search/ingestor.go @@ -148,7 +148,7 @@ func (si *Ingestor) Search( metric.DocumentsRequested.Observe(float64(len(ids))) fieldsFilter := tryParseFieldsFilter(string(sr.Q)) - docsStream, err = si.FetchDocsStream(ctx, ids, sr.Explain, fieldsFilter) + docsStream, err = si.FetchDocsStream(ctx, ids, sr.Explain, false, fieldsFilter) if err != nil { return nil, nil, 0, err } @@ -211,7 +211,13 @@ func paginateIDs(ids seq.IDSources, offset, size int) (seq.IDSources, int) { return ids, size } -func (si *Ingestor) singleDocsStream(ctx context.Context, explain bool, source uint64, ids []seq.IDSource, fields FetchFieldsFilter) (DocsIterator, error) { +func (si *Ingestor) singleDocsStream( + ctx context.Context, + explain, evalSkipMasks bool, + source uint64, + ids []seq.IDSource, + fields FetchFieldsFilter, +) (DocsIterator, error) { startTime := time.Now() host, has := si.clientBySource[source] if !has { @@ -222,7 +228,7 @@ func (si *Ingestor) singleDocsStream(ctx context.Context, explain bool, source u return nil, fmt.Errorf("can't fetch: no client for host %s", host) } - stream, err := client.Fetch(ctx, si.makeFetchReq(ids, explain, fields), + stream, err := client.Fetch(ctx, si.makeFetchReq(ids, explain, evalSkipMasks, fields), grpc.MaxCallRecvMsgSize(256*int(units.MiB)), grpc.MaxCallSendMsgSize(256*int(units.MiB)), ) @@ -286,11 +292,16 @@ type FetchFieldsFilter struct { AllowList bool } -func (si *Ingestor) FetchDocsStream(ctx context.Context, ids []seq.IDSource, explain bool, ff FetchFieldsFilter) (DocsIterator, error) { +func (si *Ingestor) FetchDocsStream( + ctx context.Context, + ids []seq.IDSource, + explain, evalSkipMasks bool, + ff FetchFieldsFilter, +) (DocsIterator, error) { errs := make([]error, 0) streams := make([]DocsIterator, 0) for source, ids := range groupIDsBySource(ids) { - if stream, err := si.singleDocsStream(ctx, explain, source, ids, ff); err != nil { + if stream, err := si.singleDocsStream(ctx, explain, evalSkipMasks, source, ids, ff); err != nil { metric.FetchErrors.Inc() errs = append(errs, err) logger.Error("fetch error", zap.Error(err), zap.String("store", si.clientBySource[source])) @@ -325,7 +336,7 @@ type FetchRequest struct { func (si *Ingestor) Documents(ctx context.Context, r FetchRequest) (DocsIterator, error) { metric.DocumentsRequested.Observe(float64(len(r.IDs))) // todo: ***REMOVED*** we fetch from both stores hot and cold there; need fix that - docsStream, err := si.FetchDocsStream(ctx, expandIDsBySources(r.IDs, si.clientBySource), false, r.FieldsFilter) + docsStream, err := si.FetchDocsStream(ctx, expandIDsBySources(r.IDs, si.clientBySource), false, true, r.FieldsFilter) if err != nil { return nil, err } @@ -350,7 +361,7 @@ func (si *Ingestor) Document(ctx context.Context, id seq.ID, ff FetchFieldsFilte return docs[0] } -func (si *Ingestor) makeFetchReq(ids []seq.IDSource, explain bool, ff FetchFieldsFilter) *storeapi.FetchRequest { +func (si *Ingestor) makeFetchReq(ids []seq.IDSource, explain, evalSkipMasks bool, ff FetchFieldsFilter) *storeapi.FetchRequest { idsWithHints := make([]*storeapi.IdWithHint, 0, len(ids)) idsStr := make([]string, 0, len(ids)) if len(ids) > 0 { @@ -379,6 +390,7 @@ func (si *Ingestor) makeFetchReq(ids []seq.IDSource, explain bool, ff FetchField Fields: ff.Fields, AllowList: ff.AllowList, }, + EvalSkipMasks: evalSkipMasks, } } diff --git a/storeapi/docs_stream.go b/storeapi/docs_stream.go index 62bc6f82..a0d516c5 100644 --- a/storeapi/docs_stream.go +++ b/storeapi/docs_stream.go @@ -20,13 +20,14 @@ type streamDocsBatch struct { } type docsStream struct { - ctx context.Context - ids seq.IDSources - totalIDs int - fetcher *fracmanager.Fetcher - fracs fracmanager.List - out chan streamDocsBatch - docsBuf [][]byte + ctx context.Context + ids seq.IDSources + totalIDs int + fetcher *fracmanager.Fetcher + fracs fracmanager.List + out chan streamDocsBatch + docsBuf [][]byte + evalSkipMasks bool } func (d *docsStream) Next() ([]byte, error) { @@ -71,7 +72,7 @@ func (d *docsStream) batchLoader() { d.ids = d.ids[l:] // fetch chunk - docs, err := d.fetcher.FetchDocs(d.ctx, d.fracs, chunk) + docs, err := d.fetcher.FetchDocs(d.ctx, d.fracs, chunk, d.evalSkipMasks) // first we send regardless of the error, // the possible error will be handled at the destination. @@ -114,14 +115,21 @@ func (d *docsStream) calcChunkSize(docs [][]byte, prevChunkSize int) int { return newChunkSize } -func newDocsStream(ctx context.Context, ids seq.IDSources, fetcher *fracmanager.Fetcher, fracs fracmanager.List) *docsStream { +func newDocsStream( + ctx context.Context, + ids seq.IDSources, + fetcher *fracmanager.Fetcher, + fracs fracmanager.List, + evalSkipMasks bool, +) *docsStream { d := docsStream{ - ctx: ctx, - ids: ids, - totalIDs: len(ids), - fetcher: fetcher, - fracs: fracs, - out: make(chan streamDocsBatch, 1), // buffered chan to async load the next batch while we are sending the prev batch to the client + ctx: ctx, + ids: ids, + totalIDs: len(ids), + fetcher: fetcher, + fracs: fracs, + out: make(chan streamDocsBatch, 1), // buffered chan to async load the next batch while we are sending the prev batch to the client + evalSkipMasks: evalSkipMasks, } go func() { diff --git a/storeapi/grpc_fetch.go b/storeapi/grpc_fetch.go index d640618c..3762aa17 100644 --- a/storeapi/grpc_fetch.go +++ b/storeapi/grpc_fetch.go @@ -68,7 +68,7 @@ func (g *GrpcV1) doFetch(ctx context.Context, req *storeapi.FetchRequest, stream dp := acquireDocFieldsFilter(req.FieldsFilter) defer releaseDocFieldsFilter(dp) - docsStream := newDocsStream(ctx, ids, g.fetchData.docFetcher, g.fracManager.Fractions()) + docsStream := newDocsStream(ctx, ids, g.fetchData.docFetcher, g.fracManager.Fractions(), req.EvalSkipMasks) for _, id := range ids { workTime := time.Now() doc, err := docsStream.Next() diff --git a/tests/integration_tests/single_test.go b/tests/integration_tests/single_test.go index 81bc0fed..af63fecd 100644 --- a/tests/integration_tests/single_test.go +++ b/tests/integration_tests/single_test.go @@ -218,7 +218,7 @@ func (s *SingleTestSuite) TestFetchHints() { ids := make(seq.IDSources, len(origIDs)) copy(ids, origIDs) - docsStreamWithHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, search.FetchFieldsFilter{}) + docsStreamWithHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, false, search.FetchFieldsFilter{}) s.Require().NoError(err) var fetched []string @@ -232,7 +232,7 @@ func (s *SingleTestSuite) TestFetchHints() { ids[i].Hint = "" } - docsStreamNoHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, search.FetchFieldsFilter{}) + docsStreamNoHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, false, search.FetchFieldsFilter{}) s.Require().NoError(err) fetched = []string{} @@ -246,7 +246,7 @@ func (s *SingleTestSuite) TestFetchHints() { ids[i].Hint = "foobar" } - docsStreamBrokenHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, search.FetchFieldsFilter{}) + docsStreamBrokenHints, err := s.Ingestor().SearchIngestor.FetchDocsStream(context.TODO(), ids, false, false, search.FetchFieldsFilter{}) s.Assert().NoError(err) fetched = []string{}