Browse Source

add comment cache

dev
xmcp 6 years ago
parent
commit
e97c939831
  1. 20
      src/Flows.js
  2. 98
      src/cache.js
  3. 30
      src/flows_api.js

20
src/Flows.js

@ -30,13 +30,17 @@ function load_single_meta(show_sidebar,token,parents) {
正在加载 #{pid}
</div>
);
Promise.all([
API.get_single(pid,token),
API.load_replies(pid,token,color_picker),
])
.then((res)=>{
const [single,replies]=res;
API.get_single(pid,token)
.then((single)=>{
single.data.variant={};
return new Promise((resolve,reject)=>{
API.load_replies_with_cache(pid,token,color_picker,parseInt(single.data.reply))
.then((replies)=>{resolve([single,replies])})
.catch(reject);
});
})
.then((res)=>{
let [single,replies]=res;
show_sidebar(
title_elem,
<FlowSidebar
@ -212,7 +216,7 @@ class FlowSidebar extends PureComponent {
loading_status: 'loading',
error_msg: null,
});
API.load_replies(this.state.info.pid,this.props.token,this.color_picker)
API.load_replies(this.state.info.pid,this.props.token,this.color_picker,null)
.then((json)=>{
this.setState((prev,props)=>({
replies: json.data,
@ -401,7 +405,7 @@ class FlowItemRow extends PureComponent {
this.setState({
reply_status: 'loading',
});
API.load_replies(this.state.info.pid,this.props.token,this.color_picker)
API.load_replies_with_cache(this.state.info.pid,this.props.token,this.color_picker,parseInt(this.state.info.reply))
.then((json)=>{
this.setState((prev,props)=>({
replies: json.data,

98
src/cache.js

@ -0,0 +1,98 @@
const CACHE_DB_VER=1;
const MAINTENANCE_STEP=500;
const MAINTENANCE_COUNT=5000;
class Cache {
constructor() {
this.db=null;
this.added_items_since_maintenance=0;
const open_req=indexedDB.open('hole_cache_db',CACHE_DB_VER);
open_req.onerror=console.error.bind(console);
open_req.onupgradeneeded=(event)=>{
console.log('comment cache db upgrade');
const db=event.target.result;
const store=db.createObjectStore('comment',{
keyPath: 'pid',
});
store.createIndex('last_access','last_access',{unique: false});
};
open_req.onsuccess=(event)=>{
console.log('comment cache db loaded');
this.db=event.target.result;
setTimeout(this.maintenance.bind(this),1);
};
}
get(pid,target_version) {
return new Promise((resolve,reject)=>{
if(!this.db)
return resolve(null);
const tx=this.db.transaction(['comment'],'readwrite');
const store=tx.objectStore('comment');
const get_req=store.get(pid);
get_req.onsuccess=()=>{
let res=get_req.result;
if(!res) {
console.log('cache miss');
resolve(null);
} else if(target_version===res.version) { // hit
console.log('cache hit');
res.last_access=+new Date();
store.put(res);
resolve(res.data);
} else { // expired
console.log('cache expired: ver',res.version,'target',target_version);
store.delete(pid);
resolve(null);
}
};
get_req.onerror=reject;
});
}
put(pid,target_version,data) {
return new Promise((resolve,reject)=>{
if(!this.db)
return resolve();
const tx=this.db.transaction(['comment'],'readwrite');
const store=tx.objectStore('comment');
store.put({
pid: pid,
version: target_version,
data: data,
last_access: +new Date(),
});
if(++this.added_items_since_maintenance===MAINTENANCE_STEP)
setTimeout(this.maintenance.bind(this),1);
});
}
maintenance() {
if(!this.db)
return;
const tx=this.db.transaction(['comment'],'readwrite');
const store=tx.objectStore('comment');
let count_req=store.count();
count_req.onsuccess=()=>{
let count=count_req.result;
if(count>MAINTENANCE_COUNT) {
console.log('comment cache db maintenance',count);
store.index('last_access').openKeyCursor().onsuccess=(e)=>{
let cur=e.target.result;
if(cur) {
console.log('maintenance: delete',cur);
store.delete(cur.primaryKey);
if(--count>MAINTENANCE_COUNT)
cur.continue();
}
};
} else {
console.log('comment cache db not full',count);
}
this.added_items_since_maintenance=0;
};
count_req.onerror=console.error.bind(console);
}
};
export let cache=new Cache();

30
src/flows_api.js

@ -1,6 +1,7 @@
import {get_json} from './infrastructure/functions';
import {PKUHELPER_ROOT} from './infrastructure/const';
import {API_BASE} from './Common';
import {cache} from './cache';
export const API_VERSION_PARAM='&PKUHelperAPI=3.0';
export {PKUHELPER_ROOT};
@ -12,7 +13,8 @@ function token_param(token) {
export {get_json};
export const API={
load_replies: (pid,token,color_picker)=>{
load_replies: (pid,token,color_picker,cache_version)=>{
pid=parseInt(pid);
return fetch(
API_BASE+'/api.php?action=getcomment'+
'&pid='+pid+
@ -25,6 +27,9 @@ export const API={
else throw new Error(JSON.stringify(json));
}
cache.put(pid,cache_version,json);
// also change load_replies_with_cache!
json.data=json.data
.sort((a,b)=>{
return parseInt(a.timestamp,10)-parseInt(b.timestamp,10);
@ -39,6 +44,29 @@ export const API={
});
},
load_replies_with_cache: (pid,token,color_picker,cache_version)=> {
pid=parseInt(pid);
return cache.get(pid,cache_version)
.then((json)=>{
if(json) {
// also change load_replies!
json.data=json.data
.sort((a,b)=>{
return parseInt(a.timestamp,10)-parseInt(b.timestamp,10);
})
.map((info)=>{
info._display_color=color_picker.get(info.name);
info.variant={};
return info;
});
return json;
}
else
return API.load_replies(pid,token,color_picker,cache_version);
});
},
set_attention: (pid,attention,token)=>{
let data=new URLSearchParams();
data.append('user_token',token);

Loading…
Cancel
Save