Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 131 additions & 119 deletions src/search/backend.tsx
Original file line number Diff line number Diff line change
@@ -1,151 +1,163 @@
import { isEqual } from 'lodash'
import { Observable } from 'rxjs'
import { distinctUntilChanged, map, mergeMap } from 'rxjs/operators'
import { catchError, distinctUntilChanged, map, mergeMap, switchMap } from 'rxjs/operators'
import { SearchOptions } from '.'
import { gql, queryGraphQL } from '../backend/graphql'
import * as GQL from '../backend/graphqlschema'
import { mutateConfigurationGraphQL } from '../configuration/backend'
import { ExtensionsControllerProps } from '../extensions/ExtensionsClientCommonContext'
import { currentConfiguration } from '../settings/configuration'
import { createAggregateError } from '../util/errors'
import { asError, createAggregateError, ErrorLike } from '../util/errors'

export function search(options: SearchOptions): Observable<GQL.ISearchResults> {
return queryGraphQL(
gql`
query Search($query: String!) {
search(query: $query) {
results {
__typename
limitHit
resultCount
approximateResultCount
missing {
name
}
cloning {
name
}
timedout {
name
}
indexUnavailable
dynamicFilters {
value
label
count
limitHit
kind
}
results {
... on Repository {
export function search(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When/how often does the returned Observable emit? (please document)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felixfbecker documented this a couple lines below

options: SearchOptions,
{ extensionsController }: ExtensionsControllerProps
): Observable<GQL.ISearchResults | ErrorLike> {
/**
* Emits whenever a search is executed, and whenever an extension registers a query transformer.
*/
return extensionsController.registries.queryTransformer.transformQuery(options.query).pipe(
switchMap(query =>
queryGraphQL(
gql`
query Search($query: String!) {
search(query: $query) {
results {
__typename
id
name
url
}
... on FileMatch {
__typename
file {
path
url
commit {
oid
}
}
repository {
name
url
}
limitHit
symbols {
resultCount
approximateResultCount
missing {
name
containerName
url
kind
}
lineMatches {
preview
lineNumber
offsetAndLengths
}
}
... on CommitSearchResult {
__typename
refs {
cloning {
name
displayName
prefix
repository {
name
}
}
sourceRefs {
timedout {
name
displayName
prefix
repository {
name
}
}
messagePreview {
value
highlights {
line
character
length
}
}
diffPreview {
indexUnavailable
dynamicFilters {
value
highlights {
line
character
length
}
label
count
limitHit
kind
}
commit {
id
repository {
results {
... on Repository {
__typename
id
name
url
}
oid
abbreviatedOID
author {
person {
... on FileMatch {
__typename
file {
path
url
commit {
oid
}
}
repository {
name
url
}
limitHit
symbols {
name
containerName
url
kind
}
lineMatches {
preview
lineNumber
offsetAndLengths
}
}
... on CommitSearchResult {
__typename
refs {
name
displayName
avatarURL
prefix
repository {
name
}
}
sourceRefs {
name
displayName
prefix
repository {
name
}
}
messagePreview {
value
highlights {
line
character
length
}
}
diffPreview {
value
highlights {
line
character
length
}
}
commit {
id
repository {
name
url
}
oid
abbreviatedOID
author {
person {
displayName
avatarURL
}
date
}
message
url
tree(path: "") {
canonicalURL
}
}
date
}
message
url
tree(path: "") {
canonicalURL
}
alert {
title
description
proposedQueries {
description
query
}
}
elapsedMilliseconds
}
}
alert {
title
description
proposedQueries {
description
query
}
}
elapsedMilliseconds
}
}
}
`,
{ query: options.query }
).pipe(
map(({ data, errors }) => {
if (!data || !data.search || !data.search.results) {
throw createAggregateError(errors)
}
return data.search.results
})
`,
{ query }
).pipe(
map(({ data, errors }) => {
if (!data || !data.search || !data.search.results) {
throw createAggregateError(errors)
}
return data.search.results
}),
catchError(error => [asError(error)])
)
)
)
}

Expand Down
12 changes: 8 additions & 4 deletions src/search/results/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { catchError, distinctUntilChanged, filter, map, startWith, switchMap, ta
import { parseSearchURLQuery, SearchOptions } from '..'
import * as GQL from '../../backend/graphqlschema'
import { PageTitle } from '../../components/PageTitle'
import { ExtensionsControllerProps } from '../../extensions/ExtensionsClientCommonContext'
import { currentConfiguration } from '../../settings/configuration'
import { eventLogger } from '../../tracking/eventLogger'
import { isErrorLike } from '../../util/errors'
import { search } from '../backend'
import { FilterChip } from '../FilterChip'
import { isSearchResults, submitSearch, toggleSearchFilter } from '../helpers'
Expand All @@ -17,7 +19,7 @@ import { SearchResultsListOld } from './SearchResultsListOld'

const UI_PAGE_SIZE = 75

interface SearchResultsProps {
interface SearchResultsProps extends ExtensionsControllerProps {
authenticatedUser: GQL.IUser | null
location: H.Location
history: H.History
Expand Down Expand Up @@ -87,16 +89,18 @@ export class SearchResults extends React.Component<SearchResultsProps, SearchRes
// Reset view state
[{ resultsOrError: undefined, didSave: false }],
// Do async search request
search(searchOptions).pipe(
search(searchOptions, this.props).pipe(
// Log telemetry
tap(
results =>
eventLogger.log('SearchResultsFetched', {
code_search: {
// 🚨 PRIVACY: never provide any private data in { code_search: { results } }.
results: {
results_count: results.results.length,
any_cloning: results.cloning.length > 0,
results_count: isErrorLike(results) ? 0 : results.results.length,
any_cloning: isErrorLike(results)
? false
: results.cloning.length > 0,
},
},
}),
Expand Down