Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
Update feeds on metadata change fixes #1969
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredlockhart committed Feb 15, 2017
1 parent a318975 commit bf8f644
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 57 deletions.
6 changes: 3 additions & 3 deletions addon/ActivityStreams.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ ActivityStreams.prototype = {
}
this._tabTracker.init(this.appURLs, this._experimentProvider.experimentId, this._store);
this._searchProvider.init();
this._initializePreviewProvider(this._metadataStore, this._tabTracker);
this._initializePreviewProvider(this._metadataStore, this._tabTracker, this._store);
this._initializePageScraper(this._previewProvider, this._tabTracker);
this._initializeShareProvider(this._tabTracker);
this._initializePrefProvider(this._tabTracker);
Expand Down Expand Up @@ -189,8 +189,8 @@ ActivityStreams.prototype = {
this._appURLHider = new AppURLHider(this.appURLs);
},

_initializePreviewProvider(metadataStore, tabTracker) {
this._previewProvider = new PreviewProvider(tabTracker, metadataStore);
_initializePreviewProvider(metadataStore, tabTracker, store) {
this._previewProvider = new PreviewProvider(tabTracker, metadataStore, store);
},

_initializePrefProvider(tabTracker) {
Expand Down
16 changes: 3 additions & 13 deletions addon/Feeds/HighlightsFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module.exports = class HighlightsFeed extends Feed {
constructor(options) {
super(options);
this.baselineRecommender = null; // Added in initializeRecommender, if the experiment is turned on
this.retryHighlightsCount = 0;
}

/**
Expand Down Expand Up @@ -60,14 +59,8 @@ module.exports = class HighlightsFeed extends Feed {
}
return PlacesProvider.links.getRecentlyVisited()
.then(links => this.options.getCachedMetadata(links, "HIGHLIGHTS_RESPONSE"))
.then(links => ({metadataLinks: links, weightedLinks: this.baselineRecommender.scoreEntries(links)}))
.then(({metadataLinks, weightedLinks}) => {
if (metadataLinks.length && !weightedLinks.length && this.retryHighlightsCount <= 5) {
this.retryHighlightsCount++;
return am.actions.Response("HIGHLIGHTS_AWAITING_METADATA");
}
return am.actions.Response("HIGHLIGHTS_RESPONSE", weightedLinks);
});
.then(links => this.baselineRecommender.scoreEntries(links))
.then(links => am.actions.Response("HIGHLIGHTS_RESPONSE", links));
}

onAction(state, action) {
Expand All @@ -80,10 +73,7 @@ module.exports = class HighlightsFeed extends Feed {
// We always want new bookmarks
this.refresh("a bookmark was added");
break;
case am.type("HIGHLIGHTS_AWAITING_METADATA"):
this.refresh("metadata for highlights is being fetched");
break;
case am.type("METADATA_FEED_UPDATED"):
case am.type("METADATA_UPDATED"):
// If the user visits a site and we don't have enough weighted highlights yet, refresh the data.
if (state.Highlights.rows.length < (HIGHLIGHTS_LENGTH + TOP_SITES_LENGTH)) {
this.refresh("there were not enough sites");
Expand Down
4 changes: 2 additions & 2 deletions addon/Feeds/MetadataFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ module.exports = class MetadataFeed extends Feed {

// if we are in the experiment, make a network request through PageScraper
if (simplePrefs.prefs["experiments.locallyFetchMetadata20"]) {
return this.options.fetchNewMetadataLocally(links, "METADATA_FEED_REQUEST").then(() => (am.actions.Response("METADATA_FEED_UPDATED")));
return this.options.fetchNewMetadataLocally(links, "METADATA_FEED_REQUEST").then(() => (am.actions.Response("METADATA_UPDATED")));
}
return this.options.fetchNewMetadata(links, "METADATA_FEED_REQUEST").then(() => (am.actions.Response("METADATA_FEED_UPDATED")));
return this.options.fetchNewMetadata(links, "METADATA_FEED_REQUEST").then(() => (am.actions.Response("METADATA_UPDATED")));
}
onAction(state, action) {
switch (action.type) {
Expand Down
9 changes: 6 additions & 3 deletions addon/PreviewProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ const DEFAULT_OPTIONS = {
initFresh: false
};

function PreviewProvider(tabTracker, metadataStore, options = {}) {
function PreviewProvider(tabTracker, metadataStore, store, options = {}) {
this.options = Object.assign({}, DEFAULT_OPTIONS, options);
this._onPrefChange = this._onPrefChange.bind(this);
this._tippyTopProvider = new TippyTopProvider();
this._tabTracker = tabTracker;
this._metadataStore = metadataStore;
this._store = store;
this.init();
}

Expand Down Expand Up @@ -366,7 +367,9 @@ PreviewProvider.prototype = {
expired_at: (this.options.metadataTTL) + Date.now(),
metadata_source: metadataSource
}));
this._metadataStore.asyncInsert(linksToInsert, true).catch(err => {
return this._metadataStore.asyncInsert(linksToInsert, true).then(() => {
this._store.dispatch({type: "METADATA_UPDATED"});
}).catch(err => {
// TODO: add more exception handling code, e.g. sending exception report
Cu.reportError(err);
});
Expand All @@ -378,7 +381,7 @@ PreviewProvider.prototype = {
*/
processAndInsertMetadata(link, metadataSource) {
const processedLink = this._processLinks([link]);
this.insertMetadata(processedLink, metadataSource);
return this.insertMetadata(processedLink, metadataSource);
},

/**
Expand Down
2 changes: 1 addition & 1 deletion common/action-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const am = new ActionManager([
"LOCALE_UPDATED",
"MANY_LINKS_CHANGED",
"MERGE_STORE",
"METADATA_FEED_UPDATED",
"METADATA_UPDATED",
"NOTIFY_BLOCK_URL",
"NOTIFY_BOOKMARK_ADD",
"NOTIFY_BOOKMARK_DELETE",
Expand Down
40 changes: 8 additions & 32 deletions content-test/addon/Feeds/HighlightsFeed.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,30 +99,6 @@ describe("HighlightsFeed", () => {
assert.lengthOf(action.data, 2);
});
});
it("should resolve with a HIGHLIGHTS_AWAITING_METADATA action if there are no weighted highlights", () => {
instance.baselineRecommender = {scoreEntries: () => []};
return instance.getData()
.then(action => {
assert.isObject(action);
assert.equal(action.type, "HIGHLIGHTS_AWAITING_METADATA");
});
});
it("should resolve with a HIGHLIGHTS_RESPONSE action if we've tried more than 5 times", () => {
instance.retryHighlightsCount = 5;
instance.baselineRecommender = {scoreEntries: () => []};
return instance.getData()
.then(action => {
assert.isObject(action);
assert.equal(action.type, "HIGHLIGHTS_AWAITING_METADATA");
assert.equal(instance.retryHighlightsCount, 6);
return instance.getData();
})
.then(action => {
assert.isObject(action);
assert.equal(action.type, "HIGHLIGHTS_RESPONSE");
assert.equal(instance.retryHighlightsCount, 6);
});
});
it("should run sites through getCachedMetadata", () => {
instance.baselineRecommender = {scoreEntries: links => links};
return instance.getData()
Expand Down Expand Up @@ -161,30 +137,30 @@ describe("HighlightsFeed", () => {
assert.calledOnce(instance.refresh);
assert.calledWith(instance.refresh, "a bookmark was added");
});
it("should call refresh on METADATA_FEED_UPDATED if there are not enough sites", () => {
it("should call refresh on METADATA_UPDATED if there are not enough sites", () => {
store.state.Highlights = {rows: Array(HIGHLIGHTS_LENGTH + TOP_SITES_LENGTH - 1).fill("site")};
instance.onAction(store.getState(), {type: "METADATA_FEED_UPDATED"});
instance.onAction(store.getState(), {type: "METADATA_UPDATED"});
assert.calledOnce(instance.refresh);
assert.calledWith(instance.refresh, "there were not enough sites");
});
it("should not call refresh on METADATA_FEED_UPDATED if there are enough sites", () => {
it("should not call refresh on METADATA_UPDATED if there are enough sites", () => {
store.state.Highlights = {rows: Array(HIGHLIGHTS_LENGTH + TOP_SITES_LENGTH).fill("site")};
instance.onAction(store.getState(), {type: "METADATA_FEED_UPDATED"});
instance.onAction(store.getState(), {type: "METADATA_UPDATED"});
assert.notCalled(instance.refresh);
});
it("should call refresh on METADATA_FEED_UPDATED if .lastUpdated is too old", () => {
it("should call refresh on METADATA_UPDATED if .lastUpdated is too old", () => {
store.state.Highlights = {rows: Array(HIGHLIGHTS_LENGTH + TOP_SITES_LENGTH).fill("site")};
instance.lastUpdated = 0;
clock.tick(HighlightsFeed.UPDATE_TIME);
instance.onAction(store.getState(), {type: "METADATA_FEED_UPDATED"});
instance.onAction(store.getState(), {type: "METADATA_UPDATED"});
assert.calledOnce(instance.refresh);
assert.calledWith(instance.refresh, "the sites were too old");
});
it("should not call refresh on METADATA_FEED_UPDATED if .lastUpdated is less than update time", () => {
it("should not call refresh on METADATA_UPDATED if .lastUpdated is less than update time", () => {
store.state.Highlights = {rows: Array(HIGHLIGHTS_LENGTH + TOP_SITES_LENGTH).fill("site")};
instance.lastUpdated = 0;
clock.tick(HighlightsFeed.UPDATE_TIME - 1);
instance.onAction(store.getState(), {type: "METADATA_FEED_UPDATED"});
instance.onAction(store.getState(), {type: "METADATA_UPDATED"});
assert.notCalled(instance.refresh);
});
it("should update the coefficients if the weightedHighlightsCoefficients pref is changed", () => {
Expand Down
2 changes: 1 addition & 1 deletion content-test/addon/Feeds/MetadataFeed.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("MetadataFeed", () => {
it("should resolve with an action, but no data", () => (
instance.getData().then(action => {
assert.isObject(action);
assert.equal(action.type, "METADATA_FEED_UPDATED");
assert.equal(action.type, "METADATA_UPDATED");
assert.isUndefined(action.data);
})
));
Expand Down
1 change: 1 addition & 0 deletions test/test-PreviewProvider-MetadataStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ before(exports, function*() {
yield gMetadataStore.asyncConnect();
let mockTabTracker = {handlePerformanceEvent() {}, generateEvent() {}};
gPreviewProvider = new PreviewProvider(mockTabTracker, gMetadataStore, {initFresh: true});
gPreviewProvider._store = {dispatch: () => {}};
gPreviewProvider._getFaviconColors = function() {
return Promise.resolve(null);
};
Expand Down
10 changes: 8 additions & 2 deletions test/test-PreviewProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,22 @@ exports.test_process_links = function(assert) {
});
};

exports.test_process_and_insert_links = function(assert) {
exports.test_process_and_insert_links = function*(assert) {
const fakeData = {"url": "http://example.com/1", "title": "Title for example.com/1"};

const mockActions = [];
gPreviewProvider._store = {dispatch: action => mockActions.push(action)};

// process and insert the links
gPreviewProvider.processAndInsertMetadata(fakeData, "metadata_source");
yield gPreviewProvider.processAndInsertMetadata(fakeData, "metadata_source");
assert.equal(gMetadataStore[0].length, 1, "saved one item");

// check the first site inserted in the metadata DB
assert.equal(gMetadataStore[0][0].url, fakeData.url, "site was saved as expected");
assert.equal(gMetadataStore[0][0].cache_key, "example.com/1", "we added a cache_key for the site");
assert.equal(gMetadataStore[0][0].metadata_source, "metadata_source", "we added a metadata_source for the site");
assert.equal(gMetadataStore[0][0].title, fakeData.title, "we added the title from the metadata for the site");
assert.equal(mockActions[0].type, "METADATA_UPDATED");
};

exports.test_look_for_link_in_DB = function*(assert) {
Expand Down Expand Up @@ -438,6 +442,7 @@ exports.test_copy_over_correct_data_from_firefox = function*(assert) {
exports.test_compute_image_sizes = function*(assert) {
let mockExperimentProvider = {data: {metadataService: false}};
gPreviewProvider = new PreviewProvider(gMockTabTracker, gMockMetadataStore, mockExperimentProvider, {initFresh: true});
gPreviewProvider._store = {dispatch: () => {}};
let metadataObj = {
url: "https://www.hasAnImage.com",
images: [{url: "data:image;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAA"}] // a 1x1 pixel image
Expand All @@ -463,6 +468,7 @@ before(exports, () => {
simplePrefs.prefs["metadata.endpoint"] = `${gEndpointPrefix}${gMetadataServiceEndpoint}`;
simplePrefs.prefs["previews.enabled"] = true;
gPreviewProvider = new PreviewProvider(gMockTabTracker, gMockMetadataStore, {initFresh: true});
gPreviewProvider._store = {dispatch: () => {}};
gPreviewProvider._getFaviconColors = function() {
return Promise.resolve(null);
};
Expand Down

0 comments on commit bf8f644

Please sign in to comment.