Handle empty subscription queue and OOP-ify

This commit is contained in:
Cadence Ember 2020-10-03 01:32:22 +13:00
parent 830c009066
commit 1ea272600c
No known key found for this signature in database
GPG Key ID: BC1C2C61CF521B17
3 changed files with 67 additions and 31 deletions

View File

@ -3,6 +3,7 @@ const db = require("../utils/db")
const {fetchChannelLatest} = require("../utils/youtube")
const {getUser} = require("../utils/getuser")
const {timeToPastText} = require("../utils/converters")
const {refresher} = require("../background/feed-update")
module.exports = [
{
@ -13,6 +14,8 @@ module.exports = [
let channels = []
let refreshed = null
if (user.token) {
// trigger a background refresh, needed if they came back from being inactive
refresher.skipWaiting()
// get channels
const subscriptions = user.getSubscriptions()
const template = Array(subscriptions.length).fill("?").join(", ")

View File

@ -61,43 +61,68 @@ class RefreshQueue {
}
}
const refreshQueue = new RefreshQueue()
class Refresher {
constructor() {
this.sym = constants.symbols.refresher
this.refreshQueue = new RefreshQueue()
this.state = this.sym.ACTIVE
this.waitingTimeout = null
this.next()
}
function refreshChannel(ucid) {
return fetch(`http://localhost:3000/api/v1/channels/${ucid}/latest`).then(res => res.json()).then(root => {
if (Array.isArray(root)) {
root.forEach(video => {
// organise
video.descriptionHtml = video.descriptionHtml.replace(/<a /g, '<a tabindex="-1" ') // should be safe
video.viewCountText = null //TODO?
// store
prepared.video_insert.run(video)
})
// update channel refreshed
prepared.channel_refreshed_update.run(Date.now(), ucid)
console.log(`updated ${root.length} videos for channel ${ucid}`)
} else if (root.identifier === "PUBLISHED_DATES_NOT_PROVIDED") {
return [] // nothing we can do. skip this iteration.
} else {
throw new Error(root.error)
refreshChannel(ucid) {
return fetch(`http://localhost:3000/api/v1/channels/${ucid}/latest`).then(res => res.json()).then(root => {
if (Array.isArray(root)) {
root.forEach(video => {
// organise
video.descriptionHtml = video.descriptionHtml.replace(/<a /g, '<a tabindex="-1" ') // should be safe
video.viewCountText = null //TODO?
// store
prepared.video_insert.run(video)
})
// update channel refreshed
prepared.channel_refreshed_update.run(Date.now(), ucid)
console.log(`updated ${root.length} videos for channel ${ucid}`)
} else if (root.identifier === "PUBLISHED_DATES_NOT_PROVIDED") {
return [] // nothing we can do. skip this iteration.
} else {
throw new Error(root.error)
}
})
}
next() {
if (this.refreshQueue.isEmpty()) {
const timeSinceLastLoop = Date.now() - this.refreshQueue.lastLoadTime
if (timeSinceLastLoop < constants.caching.subscriptions_refresh_loop_min) {
const timeToWait = constants.caching.subscriptions_refresh_loop_min - timeSinceLastLoop
console.log(`waiting ${timeToWait} before next loop`)
this.state = this.sym.WAITING
this.waitingTimeout = setTimeout(() => this.next(), timeToWait)
return
} else {
this.refreshQueue.load()
}
}
})
}
function refreshNext() {
if (refreshQueue.isEmpty()) {
const timeSinceLastLoop = Date.now() - refreshQueue.lastLoadTime
if (timeSinceLastLoop < constants.caching.subscriptions_refresh_loop_min) {
const timeToWait = constants.caching.subscriptions_refresh_loop_min - timeSinceLastLoop
console.log(`waiting ${timeToWait} before next loop`)
return setTimeout(refreshNext, timeToWait)
if (!this.refreshQueue.isEmpty()) {
this.state = this.sym.ACTIVE
const ucid = this.refreshQueue.next()
this.refreshChannel(ucid).then(() => this.next())
} else {
refreshQueue.load()
this.state = this.sym.EMPTY
}
}
const ucid = refreshQueue.next()
refreshChannel(ucid).then(refreshNext)
skipWaiting() {
if (this.state !== this.sym.ACTIVE) {
clearTimeout(this.waitingTimeout)
this.refreshQueue.lastLoadTime = 0
this.next()
}
}
}
refreshNext()
const refresher = new Refresher()
module.exports.refresher = refresher

View File

@ -19,6 +19,14 @@ const constants = {
regex: {
ucid: "[A-Za-z0-9-_]+",
video_id: "[A-Za-z0-9-_]+"
},
symbols: {
refresher: {
ACTIVE: Symbol("ACTIVE"),
WAITING: Symbol("WAITING"),
EMPTY: Symbol("EMPTY")
}
}
}