WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit ebf1579

Browse files
committed
fix: dedupe events
1 parent a035daa commit ebf1579

File tree

10 files changed

+5874
-402
lines changed

10 files changed

+5874
-402
lines changed

package-lock.json

Lines changed: 461 additions & 378 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@
4040
"@types/form-data": "^2.5.0",
4141
"@types/request": "^2.48.4",
4242
"chai": "3.4.0",
43-
"eslint": "^6.8.0",
43+
"eslint": "^7.20.0",
4444
"eslint-config-airbnb-base": "^14.1.0",
45-
"eslint-plugin-babel": "^5.3.0",
4645
"eslint-plugin-import": "^2.20.2",
4746
"mocha": "^7.2.0",
4847
"nock": "11.7.2",
@@ -125,6 +124,7 @@
125124
"slow": 1000,
126125
"normal": 400,
127126
"retries": 4,
128-
"reporter": "min"
127+
"reporter": "min",
128+
"timeout": 5000
129129
}
130130
}

src/Feed.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ class Feed {
9191
*/
9292
this.maxHistoryLength; // eslint-disable-line no-unused-expressions
9393

94+
/**
95+
* Track first load failing so skipFirstLoad can be honored on the first passing load
96+
* @type {Boolean}
97+
*/
98+
this.failedFirstLoad = true;
99+
94100
({
95101
items: this.items, url: this.url, refresh: this.refresh, userAgent: this.userAgent,
96102
eventName: this.eventName,
@@ -185,7 +191,9 @@ class Feed {
185191
})
186192
.on('response', (res) => {
187193
if (res.statusCode !== RESPONSE_CODES.OK) {
188-
this.handleError(new FeedError(`This URL returned a ${res.statusCode} status code`, 'fetch_url_error', this.url));
194+
const err = new FeedError(`This URL returned a ${res.statusCode} status code`, 'fetch_url_error', this.url);
195+
Error.captureStackTrace(err);
196+
this.handleError(err);
189197
}
190198
})
191199
.on('error', () => {

src/FeedEmitter.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,15 @@ class FeedEmitter extends EventEmitter {
9494
* @type {boolean}
9595
*/
9696
this.skipFirstLoad = options.skipFirstLoad;
97-
}
9897

98+
/**
99+
* Map of emitted event urls grouped by event.
100+
* This is to help prevent overlapping/dupe events in a single event name
101+
* Each entry set clears at the same interval as the most recently applied feed.
102+
* @type {Object}
103+
*/
104+
this.emittedUrlsPerEvent = {};
105+
}
99106

100107
/**
101108
* UserFeedConfig typedef
@@ -194,6 +201,14 @@ class FeedEmitter extends EventEmitter {
194201
this.removeFromFeedList(feedInList);
195202
}
196203

204+
if (!this.emittedUrlsPerEvent[feed.eventName]) {
205+
this.emittedUrlsPerEvent[feed.eventName] = {
206+
timeout: setTimeout(() => {
207+
this.emittedUrlsPerEvent[feed.eventName].urls = [];
208+
}, feed.refresh),
209+
urls: [],
210+
};
211+
}
197212
this.addToFeedList(feed);
198213
}
199214

@@ -231,6 +246,7 @@ class FeedEmitter extends EventEmitter {
231246
createSetInterval(feed) {
232247
const feedManager = new FeedManager(this, feed);
233248
feedManager.getContent(true);
249+
234250
return setInterval(feedManager.getContent.bind(feedManager), feed.refresh);
235251
}
236252

@@ -248,6 +264,28 @@ class FeedEmitter extends EventEmitter {
248264
const pos = this.feedList.findIndex((e) => e.url === feed.url);
249265
this.feedList.splice(pos, 1);
250266
}
267+
268+
/**
269+
* Override emit to check if emitted event has already
270+
* been emitted on the same event
271+
* **WARNING:** This is a very limited scope implementation
272+
* If we ever need to emit more than one thing at once, we should expand this
273+
* @param {string} event event name to emit
274+
* @param {Object} data event data/args
275+
* @returns {boolean} [description]
276+
*/
277+
emit(event, data) {
278+
// should only get triggered by initial-load, which we don't want to muck up memory with
279+
if (!this.emittedUrlsPerEvent[event]) {
280+
return super.emit(event, data);
281+
}
282+
283+
if (this.emittedUrlsPerEvent[event].urls.includes(data.link)) {
284+
return false;
285+
}
286+
this.emittedUrlsPerEvent[event].urls.push(data.link);
287+
return super.emit(event, data);
288+
}
251289
}
252290

253291
module.exports = FeedEmitter;

src/FeedManager.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class FeedManager {
8484
populateNewItemsInFeed(data, firstload) {
8585
data.newItems.forEach((item) => {
8686
this.feed.addItem(item);
87-
if (!(firstload && this.instance.skipFirstLoad)) {
87+
if ((firstload && !this.instance.skipFirstLoad) || !firstload) {
8888
this.instance.emit(this.feed.eventName, item);
8989
}
9090
});
@@ -96,6 +96,7 @@ class FeedManager {
9696
* @param {FeedError} error handle error
9797
*/
9898
onError(error) {
99+
console.error(error.stack);
99100
this.instance.emit('error', error);
100101
}
101102

@@ -114,9 +115,13 @@ class FeedManager {
114115
this.feed.updateHxLength(items);
115116
this.sortItemsByDate(data);
116117
this.identifyNewItems(data);
117-
this.populateNewItemsInFeed(data, firstload);
118+
119+
const innerFirst = firstload || (!firstload && this.feed.failedFirstLoad);
120+
121+
this.populateNewItemsInFeed(data, innerFirst);
118122
if (firstload && !this.instance.skipFirstLoad) {
119123
this.instance.emit(`initial-load:${this.feed.url}`, { url: this.feed.url, items: this.feed.items });
124+
this.feed.failedFirstLoad = false;
120125
}
121126
}
122127
}

0 commit comments

Comments
 (0)