Resume the pv cache source & add validation for the number of localStorage keys

This commit is contained in:
Cotes Chung 2021-04-10 19:50:55 +08:00
parent a03149cd40
commit aa54e901b1
2 changed files with 88 additions and 48 deletions

View file

@ -18,30 +18,42 @@ const getInitStatus = (function () {
}()); }());
const PvOpts = (function () { const PvOpts = (function () {
function getContent(selector) {
return $(selector).attr("content");
}
function hasContent(selector) { function hasContent(selector) {
let content = $(selector).attr("content"); let content = getContent(selector);
return (typeof content !== "undefined" && content !== false); return (typeof content !== "undefined" && content !== false);
} }
return { return {
getProxyEndpoint() { getProxyMeta() {
return $("meta[name=pv-proxy-endpoint]").attr("content"); return getContent("meta[name=pv-proxy-endpoint]");
}, },
getLocalData() { getLocalMeta() {
return $("meta[name=pv-cache-path]").attr("content"); return getContent("meta[name=pv-cache-path]");
}, },
hasProxyEndpoint() { hasProxyMeta() {
return hasContent("meta[name=pv-proxy-endpoint]"); return hasContent("meta[name=pv-proxy-endpoint]");
}, },
hasLocalData() { hasLocalMeta() {
return hasContent("meta[name=pv-cache-path]"); return hasContent("meta[name=pv-cache-path]");
} }
} }
}()); }());
const PvStorage = (function () { const PvStorage = (function () {
const KEY_PV = "pv"; const Keys = {
const KEY_CREATION = "pv_created_date"; KEY_PV: "pv",
KEY_PV_SRC: "pv_src",
KEY_CREATION: "pv_created_date"
};
const Source = {
LOCAL: "same-origin",
PROXY: "cors"
};
function get(key) { function get(key) {
return localStorage.getItem(key); return localStorage.getItem(key);
@ -51,35 +63,54 @@ const PvStorage = (function () {
localStorage.setItem(key, val); localStorage.setItem(key, val);
} }
function saveCache(pv, src) {
set(Keys.KEY_PV, pv);
set(Keys.KEY_PV_SRC, src);
set(Keys.KEY_CREATION, new Date().toJSON());
}
return { return {
keysCount() {
return Object.keys(Keys).length;
},
hasCache() { hasCache() {
return (localStorage.getItem(KEY_PV) !== null); return (localStorage.getItem(Keys.KEY_PV) !== null);
}, },
getCache() { getCache() {
// get data from browser cache return JSON.parse(localStorage.getItem(Keys.KEY_PV));
return JSON.parse(localStorage.getItem(KEY_PV));
}, },
saveCache(pv) { saveLocalCache(pv) {
set(KEY_PV, pv); saveCache(pv, Source.LOCAL);
set(KEY_CREATION, new Date().toJSON()); },
saveProxyCache(pv) {
saveCache(pv, Source.PROXY);
}, },
isExpired() { isExpired() {
let date = new Date(get(KEY_CREATION)); let date = new Date(get(Keys.KEY_CREATION));
date.setHours(date.getHours() + 1); // per hour date.setHours(date.getHours() + 1); // per hour
return Date.now() >= date.getTime(); return Date.now() >= date.getTime();
}, },
getAllPageviews() { isFromLocal() {
return PvStorage.getCache().totalsForAllResults["ga:pageviews"]; return get(Keys.KEY_PV_SRC) === Source.LOCAL;
},
isFromProxy() {
return get(Keys.KEY_PV_SRC) === Source.PROXY;
}, },
newerThan(pv) { newerThan(pv) {
return PvStorage.getAllPageviews() > pv.totalsForAllResults["ga:pageviews"]; return PvStorage.getCache().totalsForAllResults["ga:pageviews"] > pv.totalsForAllResults["ga:pageviews"];
}, },
inspectKeys() { inspectKeys() {
if (localStorage.length !== PvStorage.keysCount()) {
localStorage.clear();
return;
}
for(let i = 0; i < localStorage.length; i++){ for(let i = 0; i < localStorage.length; i++){
const key = localStorage.key(i); const key = localStorage.key(i);
switch (key) { switch (key) {
case KEY_PV: case Keys.KEY_PV:
case KEY_CREATION: case Keys.KEY_PV_SRC:
case Keys.KEY_CREATION:
break; break;
default: default:
localStorage.clear(); localStorage.clear();
@ -152,14 +183,14 @@ function displayPageviews(data) {
} }
function fetchProxyPageviews() { function fetchProxyPageviews() {
if (PvOpts.hasProxyEndpoint()) { if (PvOpts.hasProxyMeta()) {
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: PvOpts.getProxyEndpoint(), url: PvOpts.getProxyMeta(),
dataType: "jsonp", dataType: "jsonp",
jsonpCallback: "displayPageviews", jsonpCallback: "displayPageviews",
success: (data, textStatus, jqXHR) => { success: (data) => {
PvStorage.saveCache(JSON.stringify(data)); PvStorage.saveProxyCache(JSON.stringify(data));
}, },
error: (jqXHR, textStatus, errorThrown) => { error: (jqXHR, textStatus, errorThrown) => {
console.log("Failed to load pageviews from proxy server: " + errorThrown); console.log("Failed to load pageviews from proxy server: " + errorThrown);
@ -168,26 +199,19 @@ function fetchProxyPageviews() {
} }
} }
function loadPageviews(hasCache = false) { function fetchLocalPageviews(hasCache = false) {
if (PvOpts.hasLocalData()) { return fetch(PvOpts.getLocalMeta())
fetch(PvOpts.getLocalData()) .then(response => response.json())
.then((response) => response.json()) .then(data => {
.then((data) => { if (hasCache) {
// The cache from the proxy will sometimes be more recent than the local one // The cache from the proxy will sometimes be more recent than the local one
if (hasCache && PvStorage.newerThan(data)) { if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) {
return; return;
} }
displayPageviews(data);
PvStorage.saveCache(JSON.stringify(data));
})
.then(() => {
fetchProxyPageviews();
});
} else {
fetchProxyPageviews();
} }
displayPageviews(data);
PvStorage.saveLocalCache(JSON.stringify(data));
});
} }
$(function() { $(function() {
@ -199,11 +223,27 @@ $(function() {
if (PvStorage.hasCache()) { if (PvStorage.hasCache()) {
displayPageviews(PvStorage.getCache()); displayPageviews(PvStorage.getCache());
if (!PvStorage.isExpired()) {
return; if (PvStorage.isExpired()) {
if (PvOpts.hasLocalMeta()) {
fetchLocalPageviews(true).then(fetchProxyPageviews);
} else {
fetchProxyPageviews();
}
} else {
if (PvStorage.isFromLocal()) {
fetchProxyPageviews();
} }
} }
loadPageviews(PvStorage.hasCache()); } else { // no cached
if (PvOpts.hasLocalMeta()) {
fetchLocalPageviews().then(fetchProxyPageviews);
} else {
fetchProxyPageviews();
}
}
}); });

View file

@ -3,4 +3,4 @@
* © 2019 Cotes Chung * © 2019 Cotes Chung
* MIT Licensed * MIT Licensed
*/ */
const getInitStatus=function(){let t=!1;return()=>{var e=t;return t=t||!0,e}}(),PvOpts=function(){function e(e){e=$(e).attr("content");return void 0!==e&&!1!==e}return{getProxyEndpoint(){return $("meta[name=pv-proxy-endpoint]").attr("content")},getLocalData(){return $("meta[name=pv-cache-path]").attr("content")},hasProxyEndpoint(){return e("meta[name=pv-proxy-endpoint]")},hasLocalData(){return e("meta[name=pv-cache-path]")}}}(),PvStorage=function(){const t="pv",a="pv_created_date";function r(e,t){localStorage.setItem(e,t)}return{hasCache(){return null!==localStorage.getItem(t)},getCache(){return JSON.parse(localStorage.getItem(t))},saveCache(e){r(t,e),r(a,(new Date).toJSON())},isExpired(){let e=new Date((t=a,localStorage.getItem(t)));var t;return e.setHours(e.getHours()+1),Date.now()>=e.getTime()},getAllPageviews(){return PvStorage.getCache().totalsForAllResults["ga:pageviews"]},newerThan(e){return PvStorage.getAllPageviews()>e.totalsForAllResults["ga:pageviews"]},inspectKeys(){for(let e=0;e<localStorage.length;e++)switch(localStorage.key(e)){case t:case a:break;default:return void localStorage.clear()}}}}();function countUp(t,a,r){if(t<a){let e=new CountUp(r,t,a);e.error?console.error(e.error):e.start()}}function countPV(t,a){let r=0;if(void 0!==a)for(let e=0;e<a.length;++e)if(a[parseInt(e,10)][0]===t){r+=parseInt(a[parseInt(e,10)][1],10);break}return r}function tacklePV(e,t,a,r){let n=countPV(t,e);n=0===n?1:n,r?(r=parseInt(a.text().replace(/,/g,""),10),n>r&&countUp(r,n,a.attr("id"))):a.text((new Intl.NumberFormat).format(n))}function displayPageviews(e){if(void 0!==e){let t=getInitStatus();const a=e.rows;0<$("#post-list").length?$(".post-preview").each(function(){var e=$(this).find("a").attr("href");tacklePV(a,e,$(this).find(".pageviews"),t)}):0<$(".post").length&&(e=window.location.pathname,tacklePV(a,e,$("#pv"),t))}}function fetchProxyPageviews(){PvOpts.hasProxyEndpoint()&&$.ajax({type:"GET",url:PvOpts.getProxyEndpoint(),dataType:"jsonp",jsonpCallback:"displayPageviews",success:(e,t,a)=>{PvStorage.saveCache(JSON.stringify(e))},error:(e,t,a)=>{console.log("Failed to load pageviews from proxy server: "+a)}})}function loadPageviews(t=!1){PvOpts.hasLocalData()?fetch(PvOpts.getLocalData()).then(e=>e.json()).then(e=>{t&&PvStorage.newerThan(e)||(displayPageviews(e),PvStorage.saveCache(JSON.stringify(e)))}).then(()=>{fetchProxyPageviews()}):fetchProxyPageviews()}$(function(){$(".pageviews").length<=0||(PvStorage.inspectKeys(),PvStorage.hasCache()&&(displayPageviews(PvStorage.getCache()),!PvStorage.isExpired())||loadPageviews(PvStorage.hasCache()))}); const getInitStatus=function(){let t=!1;return()=>{var e=t;return t=t||!0,e}}(),PvOpts=function(){function t(e){return $(e).attr("content")}function e(e){e=t(e);return void 0!==e&&!1!==e}return{getProxyMeta(){return t("meta[name=pv-proxy-endpoint]")},getLocalMeta(){return t("meta[name=pv-cache-path]")},hasProxyMeta(){return e("meta[name=pv-proxy-endpoint]")},hasLocalMeta(){return e("meta[name=pv-cache-path]")}}}(),PvStorage=function(){const a={KEY_PV:"pv",KEY_PV_SRC:"pv_src",KEY_CREATION:"pv_created_date"},t={LOCAL:"same-origin",PROXY:"cors"};function r(e){return localStorage.getItem(e)}function o(e,t){localStorage.setItem(e,t)}function n(e,t){o(a.KEY_PV,e),o(a.KEY_PV_SRC,t),o(a.KEY_CREATION,(new Date).toJSON())}return{keysCount(){return Object.keys(a).length},hasCache(){return null!==localStorage.getItem(a.KEY_PV)},getCache(){return JSON.parse(localStorage.getItem(a.KEY_PV))},saveLocalCache(e){n(e,t.LOCAL)},saveProxyCache(e){n(e,t.PROXY)},isExpired(){let e=new Date(r(a.KEY_CREATION));return e.setHours(e.getHours()+1),Date.now()>=e.getTime()},isFromLocal(){return r(a.KEY_PV_SRC)===t.LOCAL},isFromProxy(){return r(a.KEY_PV_SRC)===t.PROXY},newerThan(e){return PvStorage.getCache().totalsForAllResults["ga:pageviews"]>e.totalsForAllResults["ga:pageviews"]},inspectKeys(){if(localStorage.length===PvStorage.keysCount())for(let e=0;e<localStorage.length;e++)switch(localStorage.key(e)){case a.KEY_PV:case a.KEY_PV_SRC:case a.KEY_CREATION:break;default:return void localStorage.clear()}else localStorage.clear()}}}();function countUp(t,a,r){if(t<a){let e=new CountUp(r,t,a);e.error?console.error(e.error):e.start()}}function countPV(t,a){let r=0;if(void 0!==a)for(let e=0;e<a.length;++e)if(a[parseInt(e,10)][0]===t){r+=parseInt(a[parseInt(e,10)][1],10);break}return r}function tacklePV(e,t,a,r){let o=countPV(t,e);o=0===o?1:o,r?(r=parseInt(a.text().replace(/,/g,""),10),o>r&&countUp(r,o,a.attr("id"))):a.text((new Intl.NumberFormat).format(o))}function displayPageviews(e){if(void 0!==e){let t=getInitStatus();const a=e.rows;0<$("#post-list").length?$(".post-preview").each(function(){var e=$(this).find("a").attr("href");tacklePV(a,e,$(this).find(".pageviews"),t)}):0<$(".post").length&&(e=window.location.pathname,tacklePV(a,e,$("#pv"),t))}}function fetchProxyPageviews(){PvOpts.hasProxyMeta()&&$.ajax({type:"GET",url:PvOpts.getProxyMeta(),dataType:"jsonp",jsonpCallback:"displayPageviews",success:e=>{PvStorage.saveProxyCache(JSON.stringify(e))},error:(e,t,a)=>{console.log("Failed to load pageviews from proxy server: "+a)}})}function fetchLocalPageviews(t=!1){return fetch(PvOpts.getLocalMeta()).then(e=>e.json()).then(e=>{t&&PvStorage.isFromProxy()&&PvStorage.newerThan(e)||(displayPageviews(e),PvStorage.saveLocalCache(JSON.stringify(e)))})}$(function(){$(".pageviews").length<=0||(PvStorage.inspectKeys(),PvStorage.hasCache()?(displayPageviews(PvStorage.getCache()),PvStorage.isExpired()?PvOpts.hasLocalMeta()?fetchLocalPageviews(!0).then(fetchProxyPageviews):fetchProxyPageviews():PvStorage.isFromLocal()&&fetchProxyPageviews()):PvOpts.hasLocalMeta()?fetchLocalPageviews().then(fetchProxyPageviews):fetchProxyPageviews())});