Skip to content
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Changed

- Send 10% of the production traffic to the new intsch service authough still uses the result from the I/O app. For the routes: autocompleteSearchSuggestions, topSearches and searchSuggestions.

## [1.77.0] - 2025-09-23

### Changed
Expand Down
4 changes: 2 additions & 2 deletions node/clients/intelligent-search-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class IntelligentSearchApi
this.locale = locale ?? tenant?.locale
}

public async topSearches() {
public async fetchTopSearches() {
return this.http.get('/top_searches', {
params: {
locale: this.locale,
Expand All @@ -87,7 +87,7 @@ export class IntelligentSearchApi
})
}

public async searchSuggestions(params: SearchSuggestionsParams) {
public async fetchSearchSuggestions(params: SearchSuggestionsParams) {
return this.http.get('/search_suggestions', {
params: { ...params, locale: this.locale },
metric: 'searchSuggestions',
Expand Down
19 changes: 19 additions & 0 deletions node/clients/intsch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import {
AutocompleteSuggestionsArgs,
AutocompleteSuggestionsResponse,
IIntelligentSearchClient,
SearchSuggestionsArgs,
SearchSuggestionsResponse,
TopSearchesResponse,
} from './types'

export class Intsch extends JanusClient implements IIntelligentSearchClient {
Expand All @@ -30,4 +33,20 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient {
}
)
}

public fetchTopSearches(): Promise<TopSearchesResponse> {
return this.http.get('/api/intelligent-search/v0/top-searches', {
params: { locale: this.locale },
metric: 'topSearches-new',
})
}

public fetchSearchSuggestions(
args: SearchSuggestionsArgs
): Promise<SearchSuggestionsResponse> {
return this.http.get('/api/intelligent-search/v0/search-suggestions', {
params: { query: args.query, locale: this.locale },
metric: 'searchSuggestions-new',
})
}
}
20 changes: 20 additions & 0 deletions node/clients/intsch/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,29 @@ export type AutocompleteSuggestionsResponse = {
}[]
}

export type TopSearchesResponse = {
searches: {
term: string
count: number
}[]
}

export type SearchSuggestionsArgs = {
query: string
}

export type SearchSuggestionsResponse = {
searches: {
term: string
count: number
}[]
}

// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface IIntelligentSearchClient {
fetchAutocompleteSuggestions(
args: AutocompleteSuggestionsArgs
): Promise<AutocompleteSuggestionsResponse>
fetchTopSearches(): Promise<TopSearchesResponse>
fetchSearchSuggestions(args: SearchSuggestionsArgs): Promise<SearchSuggestionsResponse>
}
5 changes: 5 additions & 0 deletions node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ export default new Service<Clients, RecorderState, CustomContext>({
concurrency: 10,
timeout: NINE_SECONDS_MS,
},
intsch: {
retries: 0,
concurrency: 10,
timeout: NINE_SECONDS_MS,
},
rewriter: {
timeout: SIX_SECONDS_MS,
},
Expand Down
16 changes: 16 additions & 0 deletions node/mocks/intelligent-search-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,23 @@ export class MockedIntelligentSearchApiClient
args?.fetchAutocompleteSuggestions ?? null
)
}

if (args?.fetchTopSearches instanceof Error) {
this.fetchTopSearches.mockRejectedValue(args.fetchTopSearches)
} else {
this.fetchTopSearches.mockResolvedValue(args?.fetchTopSearches ?? null)
}

if (args?.fetchSearchSuggestions instanceof Error) {
this.fetchSearchSuggestions.mockRejectedValue(args.fetchSearchSuggestions)
} else {
this.fetchSearchSuggestions.mockResolvedValue(
args?.fetchSearchSuggestions ?? null
)
}
}

public fetchAutocompleteSuggestions = jest.fn()
public fetchTopSearches = jest.fn()
public fetchSearchSuggestions = jest.fn()
}
20 changes: 20 additions & 0 deletions node/mocks/intsch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type {
IIntelligentSearchClient,
AutocompleteSuggestionsResponse,
TopSearchesResponse,
SearchSuggestionsResponse,
} from '../clients/intsch/types'

export class MockedIntschClient implements IIntelligentSearchClient {
Expand All @@ -14,11 +16,29 @@ export class MockedIntschClient implements IIntelligentSearchClient {
args?.fetchAutocompleteSuggestions ?? null
)
}

if (args?.fetchTopSearches instanceof Error) {
this.fetchTopSearches.mockRejectedValue(args.fetchTopSearches)
} else {
this.fetchTopSearches.mockResolvedValue(args?.fetchTopSearches ?? null)
}

if (args?.fetchSearchSuggestions instanceof Error) {
this.fetchSearchSuggestions.mockRejectedValue(args.fetchSearchSuggestions)
} else {
this.fetchSearchSuggestions.mockResolvedValue(
args?.fetchSearchSuggestions ?? null
)
}
}

public fetchAutocompleteSuggestions = jest.fn()
public fetchTopSearches = jest.fn()
public fetchSearchSuggestions = jest.fn()
}

export type IntelligentSearchClientArgs = {
fetchAutocompleteSuggestions?: AutocompleteSuggestionsResponse | Error
fetchTopSearches?: TopSearchesResponse | Error
fetchSearchSuggestions?: SearchSuggestionsResponse | Error
}
16 changes: 8 additions & 8 deletions node/resolvers/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ import {
getShippingOptionsFromSelectedFacets,
validMapAndQuery,
} from './utils'
import { fetchAutocompleteSuggestions } from '../../services/autocomplete'
import {
fetchAutocompleteSuggestions,
fetchTopSearches,
fetchSearchSuggestions
} from '../../services/autocomplete'
interface ProductIndentifier {
field: 'id' | 'slug' | 'ean' | 'reference' | 'sku'
value: string
Expand Down Expand Up @@ -725,10 +729,8 @@ export const queries = {
)
return getSearchMetaData(_, compatibilityArgs, ctx)
},
topSearches: async (_: any, __: any, ctx: Context) => {
const { intelligentSearchApi } = ctx.clients

return await intelligentSearchApi.topSearches()
topSearches: (_: any, __: any, ctx: Context) => {
return fetchTopSearches(ctx)
},
autocompleteSearchSuggestions: (
_: any,
Expand Down Expand Up @@ -806,8 +808,6 @@ export const queries = {
})
},
searchSuggestions: (_: any, args: { fullText: string }, ctx: Context) => {
const { intelligentSearchApi } = ctx.clients

return intelligentSearchApi.searchSuggestions({ query: args.fullText })
return fetchSearchSuggestions(ctx, args.fullText)
},
}
2 changes: 1 addition & 1 deletion node/services/autocomplete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ describe('fetchAutocompleteSuggestions', () => {
query: 'test',
})
expect(ctx.vtex.logger.error).toHaveBeenCalledWith({
message: 'Autocomplete Suggestions: "test": Results differ',
message: 'Autocomplete Suggestions: Results differ',
params: JSON.stringify({ query: 'test' }),
})
expect(response).toEqual(result)
Expand Down
43 changes: 38 additions & 5 deletions node/services/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import type { Context } from '@vtex/api'
import { compareApiResults } from '../utils/compareResults'
import type { Clients } from '../clients'

/**
* Fetches autocomplete suggestions using the legacy intelligent-search-api
*/
export function fetchAutocompleteSuggestions(
ctx: Context<Clients>,
query: string
Expand All @@ -21,10 +18,46 @@ export function fetchAutocompleteSuggestions(
intsch.fetchAutocompleteSuggestions({
query,
}),
ctx.vtex.production ? 1 : 100,
ctx.vtex.production ? 10 : 100,
ctx.vtex.logger,
{
logPrefix: `Autocomplete Suggestions: "${query}"`,
logPrefix: 'Autocomplete Suggestions',
args: { query },
}
)
}

export function fetchTopSearches(ctx: Context<Clients>) {
const { intelligentSearchApi, intsch } = ctx.clients

return compareApiResults(
() => intelligentSearchApi.fetchTopSearches(),
() => intsch.fetchTopSearches(),
ctx.vtex.production ? 10 : 100,
ctx.vtex.logger,
{
logPrefix: 'Top Searches',
args: {},
}
)
}

export function fetchSearchSuggestions(ctx: Context<Clients>, query: string) {
const { intelligentSearchApi, intsch } = ctx.clients

return compareApiResults(
() =>
intelligentSearchApi.fetchSearchSuggestions({
query,
}),
() =>
intsch.fetchSearchSuggestions({
query,
}),
ctx.vtex.production ? 10 : 100,
ctx.vtex.logger,
{
logPrefix: 'Search Suggestions',
args: { query },
}
)
Expand Down
Loading