fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

1// Copyright 2016 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package zoekt // import "github.com/sourcegraph/zoekt" 16 17import ( 18 "context" 19 "encoding/json" 20 "errors" 21 "fmt" 22 "math" 23 "reflect" 24 "strconv" 25 "time" 26 27 "github.com/sourcegraph/zoekt/query" 28) 29 30const mapHeaderBytes uint64 = 48 31const sliceHeaderBytes uint64 = 24 32const stringHeaderBytes uint64 = 16 33const pointerSize uint64 = 8 34 35// FileMatch contains all the matches within a file. 36type FileMatch struct { 37 // Ranking; the higher, the better. 38 Score float64 // TODO - hide this field? 39 40 // Experimental. Ranks is a vector containing floats in the interval [0, 1]. The 41 // length of the vector depends on the output from the ranking function at index 42 // time. 43 // 44 // This field is only set if the shard contains ranking information and 45 // SearchOptions.UseDocumentRanks is true. 46 Ranks []float64 47 48 // For debugging. Needs DebugScore set, but public so tests in 49 // other packages can print some diagnostics. 50 Debug string 51 52 FileName string 53 54 // Repository is the globally unique name of the repo of the 55 // match 56 Repository string 57 Branches []string 58 59 // One of LineMatches or ChunkMatches will be returned depending on whether 60 // the SearchOptions.ChunkMatches is set. 61 LineMatches []LineMatch 62 ChunkMatches []ChunkMatch 63 64 // RepositoryID is a Sourcegraph extension. This is the ID of Repository in 65 // Sourcegraph. 66 RepositoryID uint32 67 68 // RepositoryPriority is a Sourcegraph extension. It is used by Sourcegraph to 69 // order results from different repositories relative to each other. 70 RepositoryPriority float64 71 72 // Only set if requested 73 Content []byte 74 75 // Checksum of the content. 76 Checksum []byte 77 78 // Detected language of the result. 79 Language string 80 81 // SubRepositoryName is the globally unique name of the repo, 82 // if it came from a subrepository 83 SubRepositoryName string 84 85 // SubRepositoryPath holds the prefix where the subrepository 86 // was mounted. 87 SubRepositoryPath string 88 89 // Commit SHA1 (hex) of the (sub)repo holding the file. 90 Version string 91} 92 93func (m *FileMatch) sizeBytes() (sz uint64) { 94 // Score 95 sz += 8 96 97 // ranks 98 sz += 8 * uint64(len(m.Ranks)) 99 100 for _, s := range []string{ 101 m.Debug, 102 m.FileName, 103 m.Repository, 104 m.Language, 105 m.SubRepositoryName, 106 m.SubRepositoryPath, 107 m.Version, 108 } { 109 sz += stringHeaderBytes + uint64(len(s)) 110 } 111 112 // Branches 113 sz += sliceHeaderBytes 114 for _, s := range m.Branches { 115 sz += stringHeaderBytes + uint64(len(s)) 116 } 117 118 // LineMatches 119 sz += sliceHeaderBytes 120 for _, lm := range m.LineMatches { 121 sz += lm.sizeBytes() 122 } 123 124 // ChunkMatches 125 sz += sliceHeaderBytes 126 for _, cm := range m.ChunkMatches { 127 sz += cm.sizeBytes() 128 } 129 130 // RepositoryID 131 sz += 4 132 133 // RepositoryPriority 134 sz += 8 135 136 // Content 137 sz += sliceHeaderBytes + uint64(len(m.Content)) 138 139 // Checksum 140 sz += sliceHeaderBytes + uint64(len(m.Checksum)) 141 142 return 143} 144 145// ChunkMatch is a set of non-overlapping matches within a contiguous range of 146// lines in the file. 147type ChunkMatch struct { 148 // Content is a contiguous range of complete lines that fully contains Ranges. 149 Content []byte 150 // ContentStart is the location (inclusive) of the beginning of content 151 // relative to the beginning of the file. It will always be at the 152 // beginning of a line (Column will always be 1). 153 ContentStart Location 154 155 // FileName indicates whether this match is a match on the file name, in 156 // which case Content will contain the file name. 157 FileName bool 158 159 // Ranges is a set of matching ranges within this chunk. Each range is relative 160 // to the beginning of the file (not the beginning of Content). 161 Ranges []Range 162 163 // SymbolInfo is the symbol information associated with Ranges. If it is non-nil, 164 // its length will equal that of Ranges. Any of its elements may be nil. 165 SymbolInfo []*Symbol 166 167 Score float64 168 DebugScore string 169} 170 171func (cm *ChunkMatch) sizeBytes() (sz uint64) { 172 // Content 173 sz += sliceHeaderBytes + uint64(len(cm.Content)) 174 175 // ContentStart 176 sz += cm.ContentStart.sizeBytes() 177 178 // FileName 179 sz += 1 180 181 // Ranges 182 sz += sliceHeaderBytes 183 if len(cm.Ranges) > 0 { 184 sz += uint64(len(cm.Ranges)) * cm.Ranges[0].sizeBytes() 185 } 186 187 // SymbolInfo 188 sz += sliceHeaderBytes 189 for _, si := range cm.SymbolInfo { 190 sz += pointerSize 191 if si != nil { 192 sz += si.sizeBytes() 193 } 194 } 195 196 // Score 197 sz += 8 198 199 // DebugScore 200 sz += stringHeaderBytes + uint64(len(cm.DebugScore)) 201 202 return 203} 204 205type Range struct { 206 // The inclusive beginning of the range. 207 Start Location 208 // The exclusive end of the range. 209 End Location 210} 211 212func (r *Range) sizeBytes() uint64 { 213 return r.Start.sizeBytes() + r.End.sizeBytes() 214} 215 216type Location struct { 217 // 0-based byte offset from the beginning of the file 218 ByteOffset uint32 219 // 1-based line number from the beginning of the file 220 LineNumber uint32 221 // 1-based column number (in runes) from the beginning of line 222 Column uint32 223} 224 225func (l *Location) sizeBytes() uint64 { 226 return 3 * 4 227} 228 229// LineMatch holds the matches within a single line in a file. 230type LineMatch struct { 231 // The line in which a match was found. 232 Line []byte 233 LineStart int 234 LineEnd int 235 LineNumber int 236 237 // Before and After are only set when SearchOptions.NumContextLines is > 0 238 Before []byte 239 After []byte 240 241 // If set, this was a match on the filename. 242 FileName bool 243 244 // The higher the better. Only ranks the quality of the match 245 // within the file, does not take rank of file into account 246 Score float64 247 DebugScore string 248 249 LineFragments []LineFragmentMatch 250} 251 252func (lm *LineMatch) sizeBytes() (sz uint64) { 253 // Line 254 sz += sliceHeaderBytes + uint64(len(lm.Line)) 255 256 // LineStart, LineEnd, LineNumber 257 sz += 3 * 8 258 259 // Before 260 sz += sliceHeaderBytes + uint64(len(lm.Before)) 261 262 // After 263 sz += sliceHeaderBytes + uint64(len(lm.After)) 264 265 // FileName 266 sz += 1 267 268 // Score 269 sz += 8 270 271 // DebugScore 272 sz += stringHeaderBytes + uint64(len(lm.DebugScore)) 273 274 // LineFragments 275 sz += sliceHeaderBytes 276 for _, lf := range lm.LineFragments { 277 sz += lf.sizeBytes() 278 } 279 280 return 281} 282 283type Symbol struct { 284 Sym string 285 Kind string 286 Parent string 287 ParentKind string 288} 289 290func (s *Symbol) sizeBytes() uint64 { 291 return 4*stringHeaderBytes + uint64(len(s.Sym)+len(s.Kind)+len(s.Parent)+len(s.ParentKind)) 292} 293 294// LineFragmentMatch a segment of matching text within a line. 295type LineFragmentMatch struct { 296 // Offset within the line, in bytes. 297 LineOffset int 298 299 // Offset from file start, in bytes. 300 Offset uint32 301 302 // Number bytes that match. 303 MatchLength int 304 305 SymbolInfo *Symbol 306} 307 308func (lfm *LineFragmentMatch) sizeBytes() (sz uint64) { 309 // LineOffset 310 sz += 8 311 312 // Offset 313 sz += 4 314 315 // MatchLength 316 sz += 8 317 318 // SymbolInfo 319 sz += pointerSize 320 if lfm.SymbolInfo != nil { 321 sz += lfm.SymbolInfo.sizeBytes() 322 } 323 324 return 325} 326 327type FlushReason uint8 328 329const ( 330 FlushReasonTimerExpired FlushReason = 1 << iota 331 FlushReasonFinalFlush 332 FlushReasonMaxSize 333) 334 335var FlushReasonStrings = map[FlushReason]string{ 336 FlushReasonTimerExpired: "timer_expired", 337 FlushReasonFinalFlush: "final_flush", 338 FlushReasonMaxSize: "max_size_reached", 339} 340 341func (fr FlushReason) String() string { 342 if v, ok := FlushReasonStrings[fr]; ok { 343 return v 344 } 345 346 return "none" 347} 348 349// Stats contains interesting numbers on the search 350type Stats struct { 351 // Amount of I/O for reading contents. 352 ContentBytesLoaded int64 353 354 // Amount of I/O for reading from index. 355 IndexBytesLoaded int64 356 357 // Number of search shards that had a crash. 358 Crashes int 359 360 // Wall clock time for this search 361 Duration time.Duration 362 363 // Number of files containing a match. 364 FileCount int 365 366 // Number of files in shards that we considered. 367 ShardFilesConsidered int 368 369 // Files that we evaluated. Equivalent to files for which all 370 // atom matches (including negations) evaluated to true. 371 FilesConsidered int 372 373 // Files for which we loaded file content to verify substring matches 374 FilesLoaded int 375 376 // Candidate files whose contents weren't examined because we 377 // gathered enough matches. 378 FilesSkipped int 379 380 // Shards that we scanned to find matches. 381 ShardsScanned int 382 383 // Shards that we did not process because a query was canceled. 384 ShardsSkipped int 385 386 // Shards that we did not process because the query was rejected by the 387 // ngram filter indicating it had no matches. 388 ShardsSkippedFilter int 389 390 // Number of non-overlapping matches 391 MatchCount int 392 393 // Number of candidate matches as a result of searching ngrams. 394 NgramMatches int 395 396 // Wall clock time for queued search. 397 Wait time.Duration 398 399 // Number of times regexp was called on files that we evaluated. 400 RegexpsConsidered int 401 402 // FlushReason explains why results were flushed. 403 FlushReason FlushReason 404} 405 406func (s *Stats) sizeBytes() (sz uint64) { 407 sz = 16 * 8 // This assumes we are running on a 64-bit architecture 408 sz += 1 // FlushReason 409 410 return 411} 412 413func (s *Stats) Add(o Stats) { 414 s.ContentBytesLoaded += o.ContentBytesLoaded 415 s.IndexBytesLoaded += o.IndexBytesLoaded 416 s.Crashes += o.Crashes 417 s.FileCount += o.FileCount 418 s.FilesConsidered += o.FilesConsidered 419 s.FilesLoaded += o.FilesLoaded 420 s.FilesSkipped += o.FilesSkipped 421 s.MatchCount += o.MatchCount 422 s.NgramMatches += o.NgramMatches 423 s.ShardFilesConsidered += o.ShardFilesConsidered 424 s.ShardsScanned += o.ShardsScanned 425 s.ShardsSkipped += o.ShardsSkipped 426 s.ShardsSkippedFilter += o.ShardsSkippedFilter 427 s.Wait += o.Wait 428 s.RegexpsConsidered += o.RegexpsConsidered 429 430 // We want the first non-zero FlushReason to be sticky. This is a useful 431 // property when aggregating stats from several Zoekts. 432 if s.FlushReason == 0 { 433 s.FlushReason = o.FlushReason 434 } 435} 436 437// Zero returns true if stats is empty. 438func (s *Stats) Zero() bool { 439 if s == nil { 440 return true 441 } 442 443 return !(s.ContentBytesLoaded > 0 || 444 s.IndexBytesLoaded > 0 || 445 s.Crashes > 0 || 446 s.FileCount > 0 || 447 s.FilesConsidered > 0 || 448 s.FilesLoaded > 0 || 449 s.FilesSkipped > 0 || 450 s.MatchCount > 0 || 451 s.NgramMatches > 0 || 452 s.ShardFilesConsidered > 0 || 453 s.ShardsScanned > 0 || 454 s.ShardsSkipped > 0 || 455 s.ShardsSkippedFilter > 0 || 456 s.Wait > 0 || 457 s.RegexpsConsidered > 0) 458} 459 460// Progress contains information about the global progress of the running search query. 461// This is used by the frontend to reorder results and emit them when stable. 462// Sourcegraph specific: this is used when querying multiple zoekt-webserver instances. 463type Progress struct { 464 // Priority of the shard that was searched. 465 Priority float64 466 467 // MaxPendingPriority is the maximum priority of pending result that is being searched in parallel. 468 // This is used to reorder results when the result set is known to be stable-- that is, when a result's 469 // Priority is greater than the max(MaxPendingPriority) from the latest results of each backend, it can be returned to the user. 470 // 471 // MaxPendingPriority decreases monotonically in each SearchResult. 472 MaxPendingPriority float64 473} 474 475func (p *Progress) sizeBytes() uint64 { 476 return 2 * 8 477} 478 479// SearchResult contains search matches and extra data 480type SearchResult struct { 481 Stats 482 Progress 483 Files []FileMatch 484 485 // RepoURLs holds a repo => template string map. 486 RepoURLs map[string]string 487 488 // FragmentNames holds a repo => template string map, for 489 // the line number fragment. 490 LineFragments map[string]string 491} 492 493// SizeBytes is a best-effort estimate of the size of SearchResult in memory. 494// The estimate does not take alignment into account. The result is a lower 495// bound on the actual size in memory. 496func (sr *SearchResult) SizeBytes() (sz uint64) { 497 sz += sr.Stats.sizeBytes() 498 sz += sr.Progress.sizeBytes() 499 500 // Files 501 sz += sliceHeaderBytes 502 for _, f := range sr.Files { 503 sz += f.sizeBytes() 504 } 505 506 // RepoURLs 507 sz += mapHeaderBytes 508 for k, v := range sr.RepoURLs { 509 sz += stringHeaderBytes + uint64(len(k)) 510 sz += stringHeaderBytes + uint64(len(v)) 511 } 512 513 // LineFragments 514 sz += mapHeaderBytes 515 for k, v := range sr.LineFragments { 516 sz += stringHeaderBytes + uint64(len(k)) 517 sz += stringHeaderBytes + uint64(len(v)) 518 } 519 520 return 521} 522 523// RepositoryBranch describes an indexed branch, which is a name 524// combined with a version. 525type RepositoryBranch struct { 526 Name string 527 Version string 528} 529 530func (r RepositoryBranch) String() string { 531 return fmt.Sprintf("%s@%s", r.Name, r.Version) 532} 533 534// Repository holds repository metadata. 535type Repository struct { 536 // Sourcergaph's repository ID 537 ID uint32 538 539 // The repository name 540 Name string 541 542 // The repository URL. 543 URL string 544 545 // The physical source where this repo came from, eg. full 546 // path to the zip filename or git repository directory. This 547 // will not be exposed in the UI, but can be used to detect 548 // orphaned index shards. 549 Source string 550 551 // The branches indexed in this repo. 552 Branches []RepositoryBranch 553 554 // Nil if this is not the super project. 555 SubRepoMap map[string]*Repository 556 557 // URL template to link to the commit of a branch 558 CommitURLTemplate string 559 560 // The repository URL for getting to a file. Has access to 561 // {{Branch}}, {{Path}} 562 FileURLTemplate string 563 564 // The URL fragment to add to a file URL for line numbers. has 565 // access to {{LineNumber}}. The fragment should include the 566 // separator, generally '#' or ';'. 567 LineFragmentTemplate string 568 569 // Perf optimization: priority is set when we load the shard. It corresponds to 570 // the value of "priority" stored in RawConfig. 571 priority float64 572 573 // All zoekt.* configuration settings. 574 RawConfig map[string]string 575 576 // Importance of the repository, bigger is more important 577 Rank uint16 578 579 // IndexOptions is a hash of the options used to create the index for the 580 // repo. 581 IndexOptions string 582 583 // HasSymbols is true if this repository has indexed ctags 584 // output. Sourcegraph specific: This field is more appropriate for 585 // IndexMetadata. However, we store it here since the Sourcegraph frontend 586 // can read this structure but not IndexMetadata. 587 HasSymbols bool 588 589 // Tombstone is true if we are not allowed to search this repo. 590 Tombstone bool 591 592 // LatestCommitDate is the date of the latest commit among all indexed Branches. 593 // The date might be time.Time's 0-value if the repository was last indexed 594 // before this field was added. 595 LatestCommitDate time.Time 596 597 // FileTombstones is a set of file paths that should be ignored across all branches 598 // in this shard. 599 FileTombstones map[string]struct{} `json:",omitempty"` 600} 601 602func (r *Repository) UnmarshalJSON(data []byte) error { 603 // We define a new type so that we can use json.Unmarshal 604 // without recursing into this same method. 605 type repository *Repository 606 repo := repository(r) 607 608 err := json.Unmarshal(data, repo) 609 if err != nil { 610 return err 611 } 612 613 if v, ok := repo.RawConfig["repoid"]; ok { 614 id, _ := strconv.ParseUint(v, 10, 32) 615 r.ID = uint32(id) 616 } 617 618 if v, ok := repo.RawConfig["priority"]; ok { 619 r.priority, err = strconv.ParseFloat(v, 64) 620 if err != nil { 621 r.priority = 0 622 } 623 624 // Sourcegraph indexserver doesn't set repo.Rank, so we set it here 625 // based on priority. Setting it on read instead of during indexing 626 // allows us to avoid a complete reindex. 627 if r.Rank == 0 && r.priority > 0 { 628 l := math.Log(float64(r.priority)) 629 repo.Rank = uint16((1.0 - 1.0/math.Pow(1+l, 0.6)) * 10000) 630 } 631 } 632 return nil 633} 634 635// MergeMutable will merge x into r. mutated will be true if it made any 636// changes. err is non-nil if we needed to mutate an immutable field. 637// 638// Note: SubRepoMap, IndexOptions and HasSymbol fields are ignored. They are 639// computed while indexing so can't be synthesized from x. 640// 641// Note: We ignore RawConfig fields which are duplicated into Repository: 642// name and id. 643// 644// Note: URL, *Template fields are ignored. They are not used by Sourcegraph. 645func (r *Repository) MergeMutable(x *Repository) (mutated bool, err error) { 646 if r.ID != x.ID { 647 // Sourcegraph: strange behaviour may occur if ID changes but names don't. 648 return mutated, errors.New("ID is immutable") 649 } 650 if r.Name != x.Name { 651 // Name is encoded into the shard name on disk. We need to re-index if it 652 // changes. 653 return mutated, errors.New("Name is immutable") 654 } 655 if !reflect.DeepEqual(r.Branches, x.Branches) { 656 // Need a reindex if content changing. 657 return mutated, errors.New("Branches is immutable") 658 } 659 660 for k, v := range x.RawConfig { 661 // We ignore name and id since they are encoded into the repository. 662 if k == "name" || k == "id" { 663 continue 664 } 665 if r.RawConfig == nil { 666 mutated = true 667 r.RawConfig = make(map[string]string) 668 } 669 if r.RawConfig[k] != v { 670 mutated = true 671 r.RawConfig[k] = v 672 } 673 } 674 675 return mutated, nil 676} 677 678// IndexMetadata holds metadata stored in the index file. It contains 679// data generated by the core indexing library. 680type IndexMetadata struct { 681 IndexFormatVersion int 682 IndexFeatureVersion int 683 IndexMinReaderVersion int 684 IndexTime time.Time 685 PlainASCII bool 686 LanguageMap map[string]uint16 687 ZoektVersion string 688 ID string 689} 690 691// Statistics of a (collection of) repositories. 692type RepoStats struct { 693 // Repos is used for aggregrating the number of repositories. 694 Repos int 695 696 // Shards is the total number of search shards. 697 Shards int 698 699 // Documents holds the number of documents or files. 700 Documents int 701 702 // IndexBytes is the amount of RAM used for index overhead. 703 IndexBytes int64 704 705 // ContentBytes is the amount of RAM used for raw content. 706 ContentBytes int64 707 708 // Sourcegraph specific stats below. These are not as efficient to calculate 709 // as the above statistics. We experimentally measured about a 10% slower 710 // shard load time. However, we find these values very useful to track and 711 // computing them outside of load time introduces a lot of complexity. 712 713 // NewLinesCount is the number of newlines "\n" that appear in the zoekt 714 // indexed documents. This is not exactly the same as line count, since it 715 // will not include lines not terminated by "\n" (eg a file with no "\n", or 716 // a final line without "\n"). Note: Zoekt deduplicates documents across 717 // branches, so if a path has the same contents on multiple branches, there 718 // is only one document for it. As such that document's newlines is only 719 // counted once. See DefaultBranchNewLinesCount and AllBranchesNewLinesCount 720 // for counts which do not deduplicate. 721 NewLinesCount uint64 722 723 // DefaultBranchNewLinesCount is the number of newlines "\n" in the default 724 // branch. 725 DefaultBranchNewLinesCount uint64 726 727 // OtherBranchesNewLinesCount is the number of newlines "\n" in all branches 728 // except the default branch. 729 OtherBranchesNewLinesCount uint64 730} 731 732func (s *RepoStats) Add(o *RepoStats) { 733 // can't update Repos, since one repo may have multiple 734 // shards. 735 s.Shards += o.Shards 736 s.IndexBytes += o.IndexBytes 737 s.Documents += o.Documents 738 s.ContentBytes += o.ContentBytes 739 740 // Sourcegraph specific 741 s.NewLinesCount += o.NewLinesCount 742 s.DefaultBranchNewLinesCount += o.DefaultBranchNewLinesCount 743 s.OtherBranchesNewLinesCount += o.OtherBranchesNewLinesCount 744} 745 746type RepoListEntry struct { 747 Repository Repository 748 IndexMetadata IndexMetadata 749 Stats RepoStats 750} 751 752type MinimalRepoListEntry struct { 753 HasSymbols bool 754 Branches []RepositoryBranch 755} 756 757// RepoList holds a set of Repository metadata. 758type RepoList struct { 759 // Full response to a List request. Returned when ListOptions.Minimal is false. 760 Repos []*RepoListEntry 761 762 Crashes int 763 764 // Minimal response to a List request. Returned when ListOptions.Minimal is true. 765 Minimal map[uint32]*MinimalRepoListEntry 766 767 // Stats response to a List request. 768 // This is the aggregate RepoStats of all repos matching the input query. 769 Stats RepoStats 770} 771 772type Searcher interface { 773 Search(ctx context.Context, q query.Q, opts *SearchOptions) (*SearchResult, error) 774 775 // List lists repositories. The query `q` can only contain 776 // query.Repo atoms. 777 List(ctx context.Context, q query.Q, opts *ListOptions) (*RepoList, error) 778 Close() 779 780 // Describe the searcher for debug messages. 781 String() string 782} 783 784type ListOptions struct { 785 // Return only Minimal data per repo that Sourcegraph frontend needs. 786 Minimal bool 787} 788 789func (o *ListOptions) String() string { 790 return fmt.Sprintf("%#v", o) 791} 792 793type SearchOptions struct { 794 // Return an upper-bound estimate of eligible documents in 795 // stats.ShardFilesConsidered. 796 EstimateDocCount bool 797 798 // Return the whole file. 799 Whole bool 800 801 // Maximum number of matches: skip all processing an index 802 // shard after we found this many non-overlapping matches. 803 ShardMaxMatchCount int 804 805 // Maximum number of matches: stop looking for more matches 806 // once we have this many matches across shards. 807 TotalMaxMatchCount int 808 809 // Maximum number of matches: skip processing documents for a repository in 810 // a shard once we have found ShardRepoMaxMatchCount. 811 // 812 // A compound shard may contain multiple repositories. This will most often 813 // be set to 1 to find all repositories containing a result. 814 ShardRepoMaxMatchCount int 815 816 // Deprecated: this field is not read anymore. 817 ShardMaxImportantMatch int 818 819 // Deprecated: this field is not read anymore. 820 TotalMaxImportantMatch int 821 822 // Abort the search after this much time has passed. 823 MaxWallTime time.Duration 824 825 // FlushWallTime if non-zero will stop streaming behaviour at first and 826 // instead will collate and sort results. At FlushWallTime the results will 827 // be sent and then the behaviour will revert to the normal streaming. 828 FlushWallTime time.Duration 829 830 // Trim the number of results after collating and sorting the 831 // results 832 MaxDocDisplayCount int 833 834 // If set to a number greater than zero then up to this many number 835 // of context lines will be added before and after each matched line. 836 // Note that the included context lines might contain matches and 837 // it's up to the consumer of the result to remove those lines. 838 NumContextLines int 839 840 // If true, ChunkMatches will be returned in each FileMatch rather than LineMatches 841 // EXPERIMENTAL: the behavior of this flag may be changed in future versions. 842 ChunkMatches bool 843 844 // EXPERIMENTAL. If true, document ranks are used as additional input for 845 // sorting matches. 846 UseDocumentRanks bool 847 848 // RanksDampingFactor determines the contribution of documents ranks to the 849 // final ranking based on RRF. A value in (0,1] reduces the contribution, 850 // while a value in (-inf,0) increases it. 851 RanksDampingFactor float64 852 853 // Trace turns on opentracing for this request if true and if the Jaeger address was provided as 854 // a command-line flag 855 Trace bool 856 857 // If set, the search results will contain debug information for scoring. 858 DebugScore bool 859 860 // SpanContext is the opentracing span context, if it exists, from the zoekt client 861 SpanContext map[string]string 862} 863 864func (s *SearchOptions) String() string { 865 return fmt.Sprintf("%#v", s) 866} 867 868// Sender is the interface that wraps the basic Send method. 869type Sender interface { 870 Send(*SearchResult) 871} 872 873// Streamer adds the method StreamSearch to the Searcher interface. 874type Streamer interface { 875 Searcher 876 StreamSearch(ctx context.Context, q query.Q, opts *SearchOptions, sender Sender) (err error) 877}