Recsys: add flow and fix uncovered issues
This commit is contained in:
parent
d5c964c208
commit
e3e675455a
4 changed files with 71 additions and 21 deletions
|
@ -15,6 +15,7 @@
|
||||||
[options]
|
[options]
|
||||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
|
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
|
||||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
|
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
|
||||||
|
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore
|
||||||
module.name_mapper='^constants\(.*\)$' -> '<PROJECT_ROOT>/ui/constants\1'
|
module.name_mapper='^constants\(.*\)$' -> '<PROJECT_ROOT>/ui/constants\1'
|
||||||
module.name_mapper='^contexts\(.*\)$' -> '<PROJECT_ROOT>/ui/contexts\1'
|
module.name_mapper='^contexts\(.*\)$' -> '<PROJECT_ROOT>/ui/contexts\1'
|
||||||
module.name_mapper='^util\(.*\)$' -> '<PROJECT_ROOT>/ui/util\1'
|
module.name_mapper='^util\(.*\)$' -> '<PROJECT_ROOT>/ui/util\1'
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// @flow
|
||||||
import { RECSYS_ENDPOINT } from 'config';
|
import { RECSYS_ENDPOINT } from 'config';
|
||||||
import { selectUser } from 'redux/selectors/user';
|
import { selectUser } from 'redux/selectors/user';
|
||||||
import { makeSelectRecommendedRecsysIdForClaimId } from 'redux/selectors/search';
|
import { makeSelectRecommendedRecsysIdForClaimId } from 'redux/selectors/search';
|
||||||
|
@ -10,6 +11,7 @@ import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||||
import { selectPlayingUri, selectPrimaryUri } from 'redux/selectors/content';
|
import { selectPlayingUri, selectPrimaryUri } from 'redux/selectors/content';
|
||||||
import { selectClientSetting, selectDaemonSettings } from 'redux/selectors/settings';
|
import { selectClientSetting, selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
import { selectIsSubscribedForClaimId } from 'redux/selectors/subscriptions';
|
import { selectIsSubscribedForClaimId } from 'redux/selectors/subscriptions';
|
||||||
|
// $FlowFixMe: cannot resolve..
|
||||||
import { history } from 'ui/store';
|
import { history } from 'ui/store';
|
||||||
|
|
||||||
const recsysEndpoint = RECSYS_ENDPOINT;
|
const recsysEndpoint = RECSYS_ENDPOINT;
|
||||||
|
@ -28,7 +30,7 @@ const getClaimIdsFromUris = (uris) => {
|
||||||
: [];
|
: [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const recsys = {
|
const recsys: Recsys = {
|
||||||
entries: {},
|
entries: {},
|
||||||
debug: false,
|
debug: false,
|
||||||
/**
|
/**
|
||||||
|
@ -36,23 +38,9 @@ const recsys = {
|
||||||
* Entries are Created either when recommendedContent loads, or when recommendedContent is clicked.
|
* Entries are Created either when recommendedContent loads, or when recommendedContent is clicked.
|
||||||
* If recommended content is clicked, An Entry with parentUuid is created.
|
* If recommended content is clicked, An Entry with parentUuid is created.
|
||||||
* On page load, find an empty entry with your claimId, or create a new entry and record to it.
|
* On page load, find an empty entry with your claimId, or create a new entry and record to it.
|
||||||
* The entry will be populated with the following:
|
|
||||||
* - parentUuid // optional
|
|
||||||
* - Uuid
|
|
||||||
* - claimId
|
|
||||||
* - recommendedClaims [] // optionally empty
|
|
||||||
* - playerEvents [] // optionally empty
|
|
||||||
* - recommendedClaimsIndexClicked [] // optionally empty
|
|
||||||
* - UserId
|
|
||||||
* - pageLoadedAt
|
|
||||||
* - isEmbed
|
|
||||||
* - pageExitedAt
|
|
||||||
* - autoplay
|
|
||||||
* - recsysId // optional
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: onClickedRecommended()
|
|
||||||
* Called when RecommendedContent was clicked.
|
* Called when RecommendedContent was clicked.
|
||||||
* Adds index of clicked recommendation to parent entry
|
* Adds index of clicked recommendation to parent entry
|
||||||
* Adds new Entry with parentUuid for destination page
|
* Adds new Entry with parentUuid for destination page
|
||||||
|
@ -61,20 +49,23 @@ const recsys = {
|
||||||
*/
|
*/
|
||||||
onClickedRecommended: function (parentClaimId, newClaimId) {
|
onClickedRecommended: function (parentClaimId, newClaimId) {
|
||||||
const parentEntry = recsys.entries[parentClaimId] ? recsys.entries[parentClaimId] : null;
|
const parentEntry = recsys.entries[parentClaimId] ? recsys.entries[parentClaimId] : null;
|
||||||
const parentUuid = parentEntry['uuid'];
|
const parentUuid = parentEntry ? parentEntry['uuid'] : '';
|
||||||
const parentRecommendedClaims = parentEntry['recClaimIds'] || [];
|
const parentRecommendedClaims = parentEntry ? parentEntry['recClaimIds'] : [];
|
||||||
const parentClickedIndexes = parentEntry['recClickedVideoIdx'] || [];
|
const parentClickedIndexes = parentEntry ? parentEntry['recClickedVideoIdx'] : [];
|
||||||
const indexClicked = parentRecommendedClaims.indexOf(newClaimId);
|
const indexClicked = parentRecommendedClaims.indexOf(newClaimId);
|
||||||
|
|
||||||
if (parentUuid) {
|
if (parentUuid) {
|
||||||
recsys.createRecsysEntry(newClaimId, parentUuid);
|
recsys.createRecsysEntry(newClaimId, parentUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
parentClickedIndexes.push(indexClicked);
|
parentClickedIndexes.push(indexClicked);
|
||||||
recsys.log('onClickedRecommended', { parentClaimId, newClaimId });
|
// recsys.log('onClickedRecommended', { parentClaimId, newClaimId });
|
||||||
|
recsys.log('onClickedRecommended', newClaimId);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page was loaded. Get or Create entry and populate it with default data, plus recommended content, recsysId, etc.
|
* Page was loaded. Get or Create entry and populate it with default data,
|
||||||
|
* plus recommended content, recsysId, etc.
|
||||||
* Called from recommendedContent component
|
* Called from recommendedContent component
|
||||||
*/
|
*/
|
||||||
onRecsLoaded: function (claimId, uris, uuid = '') {
|
onRecsLoaded: function (claimId, uris, uuid = '') {
|
||||||
|
@ -86,6 +77,13 @@ const recsys = {
|
||||||
const claimIds = getClaimIdsFromUris(uris);
|
const claimIds = getClaimIdsFromUris(uris);
|
||||||
recsys.entries[claimId]['recsysId'] = makeSelectRecommendedRecsysIdForClaimId(claimId)(state) || recsysId;
|
recsys.entries[claimId]['recsysId'] = makeSelectRecommendedRecsysIdForClaimId(claimId)(state) || recsysId;
|
||||||
recsys.entries[claimId]['pageLoadedAt'] = Date.now();
|
recsys.entries[claimId]['pageLoadedAt'] = Date.now();
|
||||||
|
|
||||||
|
// It is possible that `claimIds` include `null | undefined` entries
|
||||||
|
// instead of all being strings. I don't know if we should filter it,
|
||||||
|
// or change the `recClaimIds` definition. Leaving as is for now since
|
||||||
|
// any changes could affect existing recsys data set.
|
||||||
|
// -----------
|
||||||
|
// $FlowFixMe:
|
||||||
recsys.entries[claimId]['recClaimIds'] = claimIds;
|
recsys.entries[claimId]['recClaimIds'] = claimIds;
|
||||||
}
|
}
|
||||||
recsys.log('onRecsLoaded', claimId);
|
recsys.log('onRecsLoaded', claimId);
|
||||||
|
@ -104,6 +102,7 @@ const recsys = {
|
||||||
const userId = user ? user.id : null;
|
const userId = user ? user.id : null;
|
||||||
|
|
||||||
// Make a stub entry that will be filled out on page load
|
// Make a stub entry that will be filled out on page load
|
||||||
|
// $FlowIgnore: not everything is defined since this is a stub
|
||||||
recsys.entries[claimId] = {
|
recsys.entries[claimId] = {
|
||||||
uuid: uuid || Uuidv4(),
|
uuid: uuid || Uuidv4(),
|
||||||
claimId: claimId,
|
claimId: claimId,
|
||||||
|
@ -115,10 +114,13 @@ const recsys = {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (parentUuid) {
|
if (parentUuid) {
|
||||||
|
// $FlowFixMe: 'uid' should be a number, not null.
|
||||||
recsys.entries[claimId].uid = userId || null;
|
recsys.entries[claimId].uid = userId || null;
|
||||||
recsys.entries[claimId].parentUuid = parentUuid;
|
recsys.entries[claimId].parentUuid = parentUuid;
|
||||||
} else {
|
} else {
|
||||||
|
// $FlowFixMe: 'uid' should be a number, not null.
|
||||||
recsys.entries[claimId].uid = userId;
|
recsys.entries[claimId].uid = userId;
|
||||||
|
// $FlowFixMe: 'recsysId' should be a number, not null.
|
||||||
recsys.entries[claimId].recsysId = null;
|
recsys.entries[claimId].recsysId = null;
|
||||||
recsys.entries[claimId].recClaimIds = [];
|
recsys.entries[claimId].recClaimIds = [];
|
||||||
}
|
}
|
||||||
|
@ -249,7 +251,7 @@ const recsys = {
|
||||||
const state = window.store.getState();
|
const state = window.store.getState();
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const actualPlayingUri = playingUri && playingUri.uri;
|
const actualPlayingUri = playingUri && playingUri.uri;
|
||||||
const claim = makeSelectClaimForUri(actualPlayingUri)(state);
|
const claim = makeSelectClaimForUri(actualPlayingUri || '')(state);
|
||||||
const playingClaimId = claim ? claim.claim_id : null;
|
const playingClaimId = claim ? claim.claim_id : null;
|
||||||
// const primaryUri = selectPrimaryUri(state);
|
// const primaryUri = selectPrimaryUri(state);
|
||||||
const floatingPlayer = selectClientSetting(state, SETTINGS.FLOATING_PLAYER);
|
const floatingPlayer = selectClientSetting(state, SETTINGS.FLOATING_PLAYER);
|
||||||
|
|
2
flow-typed/Claim.js
vendored
2
flow-typed/Claim.js
vendored
|
@ -58,6 +58,8 @@ declare type GenericClaim = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare type ClaimId = string;
|
||||||
|
|
||||||
declare type GenericMetadata = {
|
declare type GenericMetadata = {
|
||||||
title?: string,
|
title?: string,
|
||||||
description?: string,
|
description?: string,
|
||||||
|
|
45
flow-typed/recsys.js
vendored
Normal file
45
flow-typed/recsys.js
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
declare type Recsys = {
|
||||||
|
entries: { [ClaimId]: RecsysEntry },
|
||||||
|
debug: boolean,
|
||||||
|
onClickedRecommended: (parentClaimId: ClaimId, newClaimId: ClaimId) => void,
|
||||||
|
onRecsLoaded: (claimId: ClaimId, uris: Array<string>, uuid: string) => void,
|
||||||
|
createRecsysEntry: (claimId: ClaimId, parentUuid?: ?string, uuid?: string) => void,
|
||||||
|
sendRecsysEntry: (claimId: ClaimId, isTentative?: boolean) => ?Promise<?Response>,
|
||||||
|
onRecsysPlayerEvent: (claimId: ClaimId, event: RecsysPlaybackEvent, isEmbedded: boolean) => void,
|
||||||
|
log: (callName: string, claimId: ClaimId) => void,
|
||||||
|
onPlayerDispose: (claimId: ClaimId, isEmbedded: boolean, totalPlayingTime: number) => void,
|
||||||
|
onNavigate: () => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type RecsysEntry = {
|
||||||
|
uuid: string,
|
||||||
|
parentUuid?: string,
|
||||||
|
claimId: string,
|
||||||
|
uid?: number,
|
||||||
|
deviceId?: number,
|
||||||
|
pageLoadedAt: number, // UNIX timestamp (in UTC)
|
||||||
|
pageExitedAt: number, // UNIX timestamp (in UTC)
|
||||||
|
events: Array<RecsysPlaybackEvent>,
|
||||||
|
recsysId: string, // Recommender that produced recs
|
||||||
|
recClaimIds: Array<string>, // Recommendations
|
||||||
|
recClickedVideoIdx: Array<number>, // Video clicked index
|
||||||
|
isEmbed: boolean,
|
||||||
|
remoteIp: any, // [bytes] Caller IP address
|
||||||
|
tentative: boolean, // Visibility change rather than tab close
|
||||||
|
autoplay: boolean, // Was the last human action before this?
|
||||||
|
commentPulls: number, // How many comment pull calls did the user request?
|
||||||
|
recorded_at: number,
|
||||||
|
user_agent: string,
|
||||||
|
accept_lang: string,
|
||||||
|
tokenVerified: boolean,
|
||||||
|
totalPlayTime: number,
|
||||||
|
finalPlayPosition: number,
|
||||||
|
incognito: number, // User not logged in.
|
||||||
|
isResumedSend: boolean, // Data sent after browser is re-opened.
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type RecsysPlaybackEvent = {
|
||||||
|
event: number, // 0 = start, 1 = stop, 2 = scrub, 3 = speed, 4 = end_of_play
|
||||||
|
offset: number, // Where playback was at time of event
|
||||||
|
arg: number,
|
||||||
|
};
|
Loading…
Reference in a new issue