Investigate Oddities and improve existing Boost Feed API functionality
I refactored the feed functionality out of the API request code and into Core\Boost\Feed abstract class and implemented Core\Boost\Feeds\Boost concrete class.
In the review site the feed request response exactly matches the pre-refactored response (tested web only, need to capture a mobile request).
Example web request:
/api/v2/boost/feed?rating=2&rotator=1&sync=1&limit=150&as_activities=0&from_timestamp
The functionality appears limited, oddities found so far... (Checkbox Indicates Resolved)
-
limitin request is not honoured -
rotator=1is requested but not used anywhere -
sync=1is requested but not used anywhere -
Iterator makes a request for X boosts, if Y of those boosts are invalid or can not be resolved the iterator will return X - Y boosts, requiring additional requests to cycle the iterator (which could return few or no results again)
-
It is not implicit that boosts are always returned in ascending timestamp order
-
It is not clear what a boost 'rating' is
-
We ignore the offset requested from the iterator and instead override with the timestamp of the last boost in list with no explanation why we don't trust the iterator
added scoped labels
changed title from Investigate Oddities to Investigate Oddities
changed the description
- Developer
/api/v2/boost/fetchseems to be a copy and paste of the originalapi/v2/boost/feedcode (or could be the other way around). Unsure what calls this but I now know there are two APIs to maintain. - Developer
(Checkbox Indicates Resolved)
sync=1is used by the/fetchAPI which in sets asyncflag which sets ahydrateflag in the iterator.- Why different terms, why not make the naming consistent throughout?
hydrateset in the iterator makes the iterator fetch the entity and compare it's impressions value with the boost impressions value to determine if the boost has finished.-
It's called an
Iterator, I am not expecting an iterator to contain this functionality, how could I have known this functionality is hidden away here, not to mention this is pretty inefficient within an API call.
In the
hydratefunctionality if we determine a boost has finished we callExpire::expire()which changes the boost state to complete and generates event and notification.- Seems overkill for this one method to have it's own class, feels like it should be a part of Manager functionality
The
incrementoption is used withinhydrateto callMetrics::incrementViews()that increments some values incountersdb table.-
Metricsreferences a Mongo database which AFAIK as been abandoned/decommissioned -
Couple of private methods that are unused anywhere (
getBoostEntity,patchThumbs)
Edited by Guy Thouret - Developer
-
Iterator$listmember is public. It's only accessed by some dead code in thefetchAPI.
Edited by Guy Thouret -
added scoped label
changed the description
- Developer
BoostProvider- What's the point in registering almost every boost class in DI? Most of these are not providing a service.
Edited by Guy Thouret - Developer
-
In
Iteratorhydrateandincrementflag functionality are mutually exclusive where as the code has them nested that implies some sort of dependency. i.e. We can't increment without hydrating which is not true.
Edited by Guy Thouret -
In
- Developer
If we make a call to expire the boost it's at this point that we bloat the boost object with the hydrated owner and user objects - which will likely never be used.Should the Manager / Repository unset those objects before syncing?In this case the owner and entity objects are many times the size of the dehydrated boost object.Edited by Guy Thouret - Developer
Frontend has references to
/api/v1/boost/fetch. So there's actually another set of duplicate functionality. Rule of 3 threshold met.Boost API Usage
Boost API Platform File Reference Comment /api/v1/boost/fetchWeb src/app/lib/minds-sync/services/BoostedContentSync.jsBoostedContentSync.sync()function, usessync=1parameter. Appears to be syncing impressions from local storage to the backend/api/v1/boost/fetchWeb src/app/modules/ads/boost.tsBoostAds.fetch()function, fetching for sidebar? Usesboost:offset:sidebarlocalstorage value for tracking offset/api/v2/boost/feedWeb src/app/common/components/featured-content/featured-content.service.tsFeaturedContentService.fetch()function, relies on FeedService.fetch() which is where all the extra query params to boost feed are coming from (as_activities,from_timestamp,limit=150Hard coded limit here./api/v2/boost/feedWeb src/app/modules/newsfeed/boost-rotator/boost-rotator.component.tsNewsfeedBoostRotatorComponent.load()function, relies on FeedService.fetch() again withlimit=12andoffset=0Should FeedService throw error if limit and offset not set i.e. not be setting it's own defaults/api/v2/boost/feedWeb src/app/modules/newsfeed/feeds/boost.component.tsNewsfeedBoostComponent.load()function, relies on FeedService.fetch() again withboostfeed=true,limit=6andoffset=0Should FeedService throw error if limit and offset not set i.e. not be setting it's own defaultsapi/v1/boost/fetch/newsfeedMobile src/newsfeed/NewsfeedService.jsNewsfeedService.getBoosts()function, queries with `limitapi/v2/boost/feedMobile src/common/services/boosted-content.service.jsBoostedContentService.load()function, queries withlimit=12,offset=0Seems to be a basic service for fetching boosts usingFeedsService. Can't find any usage within mobile app?!? I think this is code copied over from the Web appEdited by Guy Thouret marked the task is requested but not used anywhere as completed
- Developer
The feeling I have is there is a massive amount of overhead/restriction in maintaining all of the various API endpoints for boost feeds and the services within the apps that consume those feeds and insert the 'boosted' content into pages.I want this to be a backend only feature consisting of a single boost service responsible for creation, serving and reporting. Boosted content should be inserted into the existing feed APIs by a call to the boost service.This will require change to the way those feeds are rendered on the frontend so that they identify and render the boosted content correctly, this render code is existing already just needs moving around.This will be resolved in this epic
Edited by Guy Thouret - Developer
-
Boost\Network\Iteratorclass has no spec test coverage.
Edited by Guy Thouret -
- Developer
-
Boost\Network\Manager::getList()fetches boosts from elasticsearch when$opts['useElastic']is set, then immediately makes a request to cassandra repository for the same boosts. I don't get what the reason for this is.
Edited by Guy Thouret -
- Developer
-
Cassandra repository doesn't store all of the values for a boost object.
@reviewed,@revoked,@rejected,@completedtimestamps are derived from the current state and not actually recorded. I.e. you are in a completed state, you are not able to know the other timestamps if you query cassandra so not sure why we even have it?!?
Edited by Guy Thouret -
Cassandra repository doesn't store all of the values for a boost object.
- Developer
While I'm at it what's with all the@prefixes? https://stackoverflow.com/questions/39153596/elasticsearch-meaning-of-symbol suggests this is a convention from early releases of elasticsearch and not a requirement. Unnecessary clutter?Discuss with @markeharding - outcome useful to have
@annotations to indicate timestamp valueEdited by Guy Thouret added scoped label and automatically removed label
- Developer
Discussed with @markeharding. Everything should be using
/v2/boost/feedLive frontend is requesting
/api/v1/boost/fetch/content?limit=8&offset=1571869035752&rating=1for sidebar content. - Developer
Investigating boosts schema in cassandra:
-
Timestamps are a mixture of seconds and milliseconds,
time_createdis ms,last_updatedis s,@prefixed timestamps are ms -
Full
ownerobject is stored for both theboostobject, theentityobject within the boost and theownerof that entity
Edited by Guy Thouret -
Timestamps are a mixture of seconds and milliseconds,
- Developer
-
In
Boost\Network\Managerwe are iterating a response object, hydrating the boost object and testing if it's valid then don't do anything with it because the object within the operator is not a reference to the one inside the iterator.
At some point there was some code that unset the boost from the response but this has been commented out long ago.
Edited by Guy Thouret -
In
removed label
marked the task We ignore the offset requested from the iterator and instead override with the timestamp of the last boost in list with no explanation why we don't trust the iterator as completed
marked the task Iterator makes a request for boosts, if of those boosts are invalid or can not be resolved the iterator will return - boosts, requiring additional requests to cycle the iterator (which could return few or no results again) as completed
added scoped label
added scoped label
changed weight to 4
added scoped label and automatically removed label
- Owner
@gthouret can we get an estimate on this task?
- Developer
Splitting this down into individual tasks with estimates.
marked the task in request is not honoured as completed
marked the task It is not clear what a boost 'rating' is as completed
closed