Skip to content

Commit 8460b48

Browse files
committed
Implement shadow traffic comparisson to facets and productSearch
1 parent 3c263b9 commit 8460b48

File tree

4 files changed

+95
-44
lines changed

4 files changed

+95
-44
lines changed

node/services/facets.test.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { fetchFacets } from './facets'
22
import { createContext } from '../mocks/contextFactory'
33
import type { FacetsInput } from '../typings/Search'
4+
import * as compareResultsModule from '../utils/compareResults'
45

56
describe('fetchFacets service', () => {
67
const mockFacetsResponse = {
@@ -32,40 +33,48 @@ describe('fetchFacets service', () => {
3233
jest.clearAllMocks()
3334
})
3435

35-
it('should use intelligentSearchApi when shouldUseNewPLPEndpoint is false', async () => {
36+
it('should use intsch when shouldUseNewPLPEndpoint is true', async () => {
3637
const ctx = createContext({
3738
accountName: 'testaccount',
3839
appSettings: {
39-
shouldUseNewPLPEndpoint: false,
40+
shouldUseNewPLPEndpoint: true,
4041
},
41-
intelligentSearchApiSettings: {
42+
intschSettings: {
4243
facets: mockFacetsResponse,
4344
},
4445
})
4546

4647
const result = await fetchFacets(ctx, mockArgs, mockSelectedFacets)
4748

48-
expect(ctx.clients.intelligentSearchApi.facets).toHaveBeenCalled()
49-
expect(ctx.clients.intsch.facets).not.toHaveBeenCalled()
49+
expect(ctx.clients.intsch.facets).toHaveBeenCalled()
50+
expect(ctx.clients.intelligentSearchApi.facets).not.toHaveBeenCalled()
5051
expect(result).toEqual(mockFacetsResponse)
5152
})
5253

53-
it('should use intsch when shouldUseNewPLPEndpoint is true', async () => {
54+
it('should compare both APIs when shouldUseNewPLPEndpoint is undefined', async () => {
5455
const ctx = createContext({
5556
accountName: 'testaccount',
5657
appSettings: {
57-
shouldUseNewPLPEndpoint: true,
58+
shouldUseNewPLPEndpoint: undefined,
59+
},
60+
intelligentSearchApiSettings: {
61+
facets: mockFacetsResponse,
5862
},
5963
intschSettings: {
6064
facets: mockFacetsResponse,
6165
},
6266
})
6367

68+
const compareApiResultsSpy = jest
69+
.spyOn(compareResultsModule, 'compareApiResults')
70+
.mockResolvedValue(mockFacetsResponse)
71+
6472
const result = await fetchFacets(ctx, mockArgs, mockSelectedFacets)
6573

66-
expect(ctx.clients.intsch.facets).toHaveBeenCalled()
67-
expect(ctx.clients.intelligentSearchApi.facets).not.toHaveBeenCalled()
74+
expect(compareApiResultsSpy).toHaveBeenCalled()
6875
expect(result).toEqual(mockFacetsResponse)
76+
77+
compareApiResultsSpy.mockRestore()
6978
})
7079

7180
it('should handle shipping options correctly', async () => {
@@ -107,4 +116,3 @@ describe('fetchFacets service', () => {
107116
expect(ctx.translated).toBe(true)
108117
})
109118
})
110-

node/services/facets.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { buildAttributePath } from '../commons/compatibility-layer'
2+
import { compareApiResults } from '../utils/compareResults'
23
import { fetchAppSettings } from './settings'
34
import type { FacetsInput } from '../typings/Search'
45

@@ -69,8 +70,7 @@ async function fetchFacetsFromIntsch(
6970
}
7071

7172
/**
72-
* Facets service that extracts facets fetching logic and implements flag-based routing
73-
* using intelligentSearchApi as primary and intsch as alternative based on shouldUseNewPLPEndpoint flag
73+
* Facets service that extracts facets fetching logic and implements comparison or flag-based routing
7474
*/
7575
export async function fetchFacets(
7676
ctx: Context,
@@ -80,11 +80,24 @@ export async function fetchFacets(
8080
) {
8181
const { shouldUseNewPLPEndpoint } = await fetchAppSettings(ctx)
8282

83-
// Check if current account should use intsch directly
83+
// If flag is explicitly true, use intsch
8484
if (shouldUseNewPLPEndpoint) {
8585
return fetchFacetsFromIntsch(ctx, args, selectedFacets, shippingOptions)
8686
}
8787

88-
return fetchFacetsFromBiggy(ctx, args, selectedFacets, shippingOptions)
88+
// If flag is undefined, compare both APIs
89+
return compareApiResults(
90+
() => fetchFacetsFromBiggy(ctx, args, selectedFacets, shippingOptions),
91+
() => fetchFacetsFromIntsch(ctx, args, selectedFacets, shippingOptions),
92+
ctx.vtex.production ? 10 : 100,
93+
ctx.vtex.logger,
94+
{
95+
logPrefix: 'Facets',
96+
args: {
97+
fullText: args.fullText,
98+
selectedFacets,
99+
shippingOptions,
100+
},
101+
}
102+
)
89103
}
90-

node/services/productSearch.test.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { fetchProductSearch } from './productSearch'
22
import { createContext } from '../mocks/contextFactory'
33
import type { ProductSearchInput } from '../typings/Search'
4+
import * as compareResultsModule from '../utils/compareResults'
45

56
describe('fetchProductSearch service', () => {
67
const mockProductSearchResponse = {
@@ -29,46 +30,58 @@ describe('fetchProductSearch service', () => {
2930
jest.clearAllMocks()
3031
})
3132

32-
it('should use intelligentSearchApi when shouldUseNewPLPEndpoint is false', async () => {
33+
it('should use intsch when shouldUseNewPLPEndpoint is true', async () => {
3334
const ctx = createContext({
3435
accountName: 'testaccount',
3536
appSettings: {
36-
shouldUseNewPLPEndpoint: false,
37+
shouldUseNewPLPEndpoint: true,
3738
},
38-
intelligentSearchApiSettings: {
39+
intschSettings: {
3940
productSearch: mockProductSearchResponse,
4041
},
4142
})
4243

4344
const result = await fetchProductSearch(ctx, mockArgs, mockSelectedFacets)
4445

45-
expect(ctx.clients.intelligentSearchApi.productSearch).toHaveBeenCalled()
46-
expect(ctx.clients.intsch.productSearch).not.toHaveBeenCalled()
46+
expect(ctx.clients.intsch.productSearch).toHaveBeenCalled()
47+
expect(
48+
ctx.clients.intelligentSearchApi.productSearch
49+
).not.toHaveBeenCalled()
4750
expect(result).toEqual({
4851
searchState: undefined,
4952
...mockProductSearchResponse,
5053
})
5154
})
5255

53-
it('should use intsch when shouldUseNewPLPEndpoint is true', async () => {
56+
it('should compare both APIs when shouldUseNewPLPEndpoint is undefined', async () => {
5457
const ctx = createContext({
5558
accountName: 'testaccount',
5659
appSettings: {
57-
shouldUseNewPLPEndpoint: true,
60+
shouldUseNewPLPEndpoint: undefined,
61+
},
62+
intelligentSearchApiSettings: {
63+
productSearch: mockProductSearchResponse,
5864
},
5965
intschSettings: {
6066
productSearch: mockProductSearchResponse,
6167
},
6268
})
6369

64-
const result = await fetchProductSearch(ctx, mockArgs, mockSelectedFacets)
65-
66-
expect(ctx.clients.intsch.productSearch).toHaveBeenCalled()
67-
expect(ctx.clients.intelligentSearchApi.productSearch).not.toHaveBeenCalled()
68-
expect(result).toEqual({
70+
const mockResult = {
6971
searchState: undefined,
7072
...mockProductSearchResponse,
71-
})
73+
}
74+
75+
const compareApiResultsSpy = jest
76+
.spyOn(compareResultsModule, 'compareApiResults')
77+
.mockResolvedValue(mockResult)
78+
79+
const result = await fetchProductSearch(ctx, mockArgs, mockSelectedFacets)
80+
81+
expect(compareApiResultsSpy).toHaveBeenCalled()
82+
expect(result).toEqual(mockResult)
83+
84+
compareApiResultsSpy.mockRestore()
7285
})
7386

7487
it('should handle shipping options correctly', async () => {
@@ -200,4 +213,3 @@ describe('fetchProductSearch service', () => {
200213
)
201214
})
202215
})
203-

node/services/productSearch.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { buildAttributePath, convertOrderBy } from '../commons/compatibility-layer'
1+
import {
2+
buildAttributePath,
3+
convertOrderBy,
4+
} from '../commons/compatibility-layer'
25
import { getWorkspaceSearchParamsFromStorage } from '../routes/workspaceSearchParams'
6+
import { compareApiResults } from '../utils/compareResults'
37
import { fetchAppSettings } from './settings'
48
import type { ProductSearchInput } from '../typings/Search'
59

@@ -19,10 +23,7 @@ async function fetchProductSearchFromBiggy(
1923
shippingOptions?: string[]
2024
) {
2125
const { intelligentSearchApi } = ctx.clients
22-
const {
23-
fullText,
24-
advertisementOptions = defaultAdvertisementOptions,
25-
} = args
26+
const { fullText, advertisementOptions = defaultAdvertisementOptions } = args
2627

2728
const workspaceSearchParams = await getWorkspaceSearchParamsFromStorage(ctx)
2829

@@ -64,10 +65,7 @@ async function fetchProductSearchFromIntsch(
6465
shippingOptions?: string[]
6566
) {
6667
const { intsch } = ctx.clients
67-
const {
68-
fullText,
69-
advertisementOptions = defaultAdvertisementOptions,
70-
} = args
68+
const { fullText, advertisementOptions = defaultAdvertisementOptions } = args
7169

7270
const workspaceSearchParams = await getWorkspaceSearchParamsFromStorage(ctx)
7371

@@ -100,8 +98,7 @@ async function fetchProductSearchFromIntsch(
10098
}
10199

102100
/**
103-
* ProductSearch service that extracts product search fetching logic and implements flag-based routing
104-
* using intelligentSearchApi as primary and intsch as alternative based on shouldUseNewPLPEndpoint flag
101+
* ProductSearch service that extracts product search fetching logic and implements comparison or flag-based routing
105102
*/
106103
export async function fetchProductSearch(
107104
ctx: Context,
@@ -111,11 +108,32 @@ export async function fetchProductSearch(
111108
) {
112109
const { shouldUseNewPLPEndpoint } = await fetchAppSettings(ctx)
113110

114-
// Check if current account should use intsch directly
115111
if (shouldUseNewPLPEndpoint) {
116-
return fetchProductSearchFromIntsch(ctx, args, selectedFacets, shippingOptions)
112+
return fetchProductSearchFromIntsch(
113+
ctx,
114+
args,
115+
selectedFacets,
116+
shippingOptions
117+
)
117118
}
118119

119-
return fetchProductSearchFromBiggy(ctx, args, selectedFacets, shippingOptions)
120+
return compareApiResults(
121+
() =>
122+
fetchProductSearchFromBiggy(ctx, args, selectedFacets, shippingOptions),
123+
() =>
124+
fetchProductSearchFromIntsch(ctx, args, selectedFacets, shippingOptions),
125+
ctx.vtex.production ? 10 : 100,
126+
ctx.vtex.logger,
127+
{
128+
logPrefix: 'ProductSearch',
129+
args: {
130+
fullText: args.fullText,
131+
query: args.query,
132+
from: args.from,
133+
to: args.to,
134+
selectedFacets,
135+
shippingOptions,
136+
},
137+
}
138+
)
120139
}
121-

0 commit comments

Comments
 (0)