send recsys powered-by #6875

Merged
jessopb merged 4 commits from recsys-sendPoweredBy into master 2021-08-17 16:03:25 +02:00
6 changed files with 62 additions and 19 deletions
Showing only changes of commit 4cd6dc01ef - Show all commits

View file

@ -28,7 +28,7 @@ declare type SearchOptions = {
declare type SearchState = { declare type SearchState = {
options: SearchOptions, options: SearchOptions,
urisByQuery: {}, resultsByQuery: {},
hasReachedMaxResultsLength: {}, hasReachedMaxResultsLength: {},
searching: boolean, searching: boolean,
}; };
@ -40,6 +40,7 @@ declare type SearchSuccess = {
from: number, from: number,
size: number, size: number,
uris: Array<string>, uris: Array<string>,
recsys: string,
}, },
}; };

View file

@ -6,6 +6,7 @@ import {
makeSelectRecommendedClaimIds, makeSelectRecommendedClaimIds,
makeSelectRecommendationClicks, makeSelectRecommendationClicks,
} from 'redux/selectors/content'; } from 'redux/selectors/content';
import { makeSelectRecommendedRecsysIdForClaimId } from 'redux/selectors/search';
const VERSION = '0.0.1'; const VERSION = '0.0.1';
@ -36,7 +37,7 @@ function createRecsys(claimId, userId, events, loadedAt, isEmbed) {
claimId: claimId, claimId: claimId,
pageLoadedAt: pageLoadedAt, pageLoadedAt: pageLoadedAt,
pageExitedAt: pageExitedAt, pageExitedAt: pageExitedAt,
recsysId: recsysId, recsysId: makeSelectRecommendedRecsysIdForClaimId(claimId)(state) || recsysId,
recClaimIds: makeSelectRecommendedClaimIds(claimId)(state), recClaimIds: makeSelectRecommendedClaimIds(claimId)(state),
recClickedVideoIdx: makeSelectRecommendationClicks(claimId)(state), recClickedVideoIdx: makeSelectRecommendationClicks(claimId)(state),
events: events, events: events,

View file

@ -61,13 +61,14 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
lighthouse lighthouse
.search(queryWithOptions) .search(queryWithOptions)
.then((data: Array<{ name: string, claimId: string }>) => { .then((data: { body: Array<{ name: string, claimId: string }>, poweredBy: string }) => {
const { body: result, poweredBy } = data;
const uris = []; const uris = [];
const actions = []; const actions = [];
data.forEach((result) => { result.forEach((item) => {
if (result) { if (item) {
const { name, claimId } = result; const { name, claimId } = item;
const urlObj: LbryUrlObj = {}; const urlObj: LbryUrlObj = {};
if (name.startsWith('@')) { if (name.startsWith('@')) {
@ -94,6 +95,7 @@ export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
from: from, from: from,
size: size, size: size,
uris, uris,
recsys: poweredBy,
}, },
}); });
dispatch(batchActions(...actions)); dispatch(batchActions(...actions));

View file

@ -17,7 +17,7 @@ const defaultState: SearchState = {
[SEARCH_OPTIONS.MEDIA_IMAGE]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_IMAGE), [SEARCH_OPTIONS.MEDIA_IMAGE]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_IMAGE),
[SEARCH_OPTIONS.MEDIA_APPLICATION]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_APPLICATION), [SEARCH_OPTIONS.MEDIA_APPLICATION]: defaultSearchTypes.includes(SEARCH_OPTIONS.MEDIA_APPLICATION),
}, },
urisByQuery: {}, resultsByQuery: {},
hasReachedMaxResultsLength: {}, hasReachedMaxResultsLength: {},
searching: false, searching: false,
}; };
@ -29,21 +29,23 @@ export default handleActions(
searching: true, searching: true,
}), }),
[ACTIONS.SEARCH_SUCCESS]: (state: SearchState, action: SearchSuccess): SearchState => { [ACTIONS.SEARCH_SUCCESS]: (state: SearchState, action: SearchSuccess): SearchState => {
const { query, uris, from, size } = action.data; const { query, uris, from, size, recsys } = action.data;
const normalizedQuery = createNormalizedSearchKey(query); const normalizedQuery = createNormalizedSearchKey(query);
const urisForQuery = state.resultsByQuery[normalizedQuery] && state.resultsByQuery[normalizedQuery]['uris'];
let newUris = uris; let newUris = uris;
if (from !== 0 && state.urisByQuery[normalizedQuery]) { if (from !== 0 && urisForQuery) {
newUris = Array.from(new Set(state.urisByQuery[normalizedQuery].concat(uris))); newUris = Array.from(new Set(urisForQuery.concat(uris)));
} }
// The returned number of urls is less than the page size, so we're on the last page // The returned number of urls is less than the page size, so we're on the last page
const noMoreResults = size && uris.length < size; const noMoreResults = size && uris.length < size;
const results = { uris: newUris, recsys };
return { return {
...state, ...state,
searching: false, searching: false,
urisByQuery: Object.assign({}, state.urisByQuery, { [normalizedQuery]: newUris }), resultsByQuery: Object.assign({}, state.resultsByQuery, { [normalizedQuery]: results }),
hasReachedMaxResultsLength: Object.assign({}, state.hasReachedMaxResultsLength, { hasReachedMaxResultsLength: Object.assign({}, state.hasReachedMaxResultsLength, {
[normalizedQuery]: noMoreResults, [normalizedQuery]: noMoreResults,
}), }),

View file

@ -4,6 +4,7 @@ import { selectShowMatureContent } from 'redux/selectors/settings';
import { import {
parseURI, parseURI,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimForClaimId,
makeSelectClaimIsNsfw, makeSelectClaimIsNsfw,
buildURI, buildURI,
isClaimNsfw, isClaimNsfw,
@ -28,7 +29,7 @@ export const selectIsSearching: (state: State) => boolean = createSelector(selec
export const selectSearchUrisByQuery: (state: State) => { [string]: Array<string> } = createSelector( export const selectSearchUrisByQuery: (state: State) => { [string]: Array<string> } = createSelector(
selectState, selectState,
(state) => state.urisByQuery (state) => state.resultsByQuery
); );
export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = createSelector( export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = createSelector(
@ -42,9 +43,9 @@ export const makeSelectSearchUris = (query: string): ((state: State) => Array<st
if (query) { if (query) {
query = query.replace(/^lbry:\/\//i, '').replace(/\//, ' '); query = query.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
const normalizedQuery = createNormalizedSearchKey(query); const normalizedQuery = createNormalizedSearchKey(query);
return byQuery[normalizedQuery]; return byQuery[normalizedQuery] && byQuery[normalizedQuery]['uris'];
} }
return byQuery[query]; return byQuery[query] && byQuery[query]['uris'];
}); });
export const makeSelectHasReachedMaxResultsLength = (query: string): ((state: State) => boolean) => export const makeSelectHasReachedMaxResultsLength = (query: string): ((state: State) => boolean) =>
@ -84,16 +85,47 @@ export const makeSelectRecommendedContentForUri = (uri: string) =>
const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options); const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options);
const normalizedSearchQuery = createNormalizedSearchKey(searchQuery); const normalizedSearchQuery = createNormalizedSearchKey(searchQuery);
let searchUris = searchUrisByQuery[normalizedSearchQuery]; let searchResult = searchUrisByQuery[normalizedSearchQuery];
if (searchUris) { if (searchResult) {
searchUris = searchUris.filter((searchUri) => searchUri !== currentUri); recommendedContent = searchResult['uris'].filter((searchUri) => searchUri !== currentUri);
recommendedContent = searchUris;
} }
} }
return recommendedContent; return recommendedContent;
} }
); );
export const makeSelectRecommendedRecsysIdForClaimId = (claimId: string) =>
createSelector(makeSelectClaimForClaimId(claimId), selectSearchUrisByQuery, (claim, searchUrisByQuery) => {
// TODO: DRY this out.
let poweredBy;
if (claim) {
const isMature = isClaimNsfw(claim);
const { title } = claim.value;
if (!title) {
return;
}
const options: {
related_to?: string,
nsfw?: boolean,
isBackgroundSearch?: boolean,
} = { related_to: claim.claim_id, isBackgroundSearch: true };
options['nsfw'] = isMature;
const searchQuery = getSearchQueryString(title.replace(/\//, ' '), options);
const normalizedSearchQuery = createNormalizedSearchKey(searchQuery);
let searchResult = searchUrisByQuery[normalizedSearchQuery];
if (searchResult) {
poweredBy = searchResult.recsys;
} else {
return normalizedSearchQuery;
}
}
return poweredBy;
});
export const makeSelectWinningUriForQuery = (query: string) => { export const makeSelectWinningUriForQuery = (query: string) => {
const uriFromQuery = `lbry://${query}`; const uriFromQuery = `lbry://${query}`;

View file

@ -1,4 +1,9 @@
// @flow // @flow
export default function handleFetchResponse(response: Response): Promise<any> { export default function handleFetchResponse(response: Response): Promise<any> {
return response.status === 200 ? Promise.resolve(response.json()) : Promise.reject(new Error(response.statusText)); const headers = response.headers;
const poweredBy = headers.get('x-powered-by');
return response.status === 200
? response.json().then((body) => ({ body, poweredBy }))
: Promise.reject(new Error(response.statusText));
} }