optimizations to the lazy loading - expanding tree now takes only one request

This commit is contained in:
azivner 2018-04-16 23:13:33 -04:00
parent 82de1c88d4
commit b4005a7ffe
5 changed files with 67 additions and 66 deletions

View file

@ -14,13 +14,10 @@ class NoteShort {
} }
async getBranches() { async getBranches() {
const branches = []; const branchIds = this.treeCache.parents[this.noteId].map(
parentNoteId => this.treeCache.getBranchIdByChildParent(this.noteId, parentNoteId));
for (const parentNoteId of this.treeCache.parents[this.noteId]) { return this.treeCache.getBranches(branchIds);
branches.push(await this.treeCache.getBranchByChildParent(this.noteId, parentNoteId));
}
return branches;
} }
hasChildren() { hasChildren() {
@ -33,13 +30,10 @@ class NoteShort {
return []; return [];
} }
const branches = []; const branchIds = this.treeCache.children[this.noteId].map(
childNoteId => this.treeCache.getBranchIdByChildParent(childNoteId, this.noteId));
for (const childNoteId of this.treeCache.children[this.noteId]) { return await this.treeCache.getBranches(branchIds);
branches.push(await this.treeCache.getBranchByChildParent(childNoteId, this.noteId));
}
return branches;
} }
async __getNotes(noteIds) { async __getNotes(noteIds) {
@ -47,13 +41,7 @@ class NoteShort {
return []; return [];
} }
const notes = []; return this.treeCache.getNotes(noteIds);
for (const noteId of noteIds) {
notes.push(await this.treeCache.getNote(noteId));
}
return notes;
} }
async getParentNotes() { async getParentNotes() {

View file

@ -375,7 +375,7 @@ async function loadTree() {
startNotePath = getNotePathFromAddress(); startNotePath = getNotePathFromAddress();
} }
return await treeBuilder.prepareTree(resp.notes, resp.branches, resp.parentToChildren); return await treeBuilder.prepareTree(resp.notes, resp.branches, resp.relations);
} }
function collapseTree(node = null) { function collapseTree(node = null) {

View file

@ -5,10 +5,10 @@ import server from "./server.js";
import treeCache from "./tree_cache.js"; import treeCache from "./tree_cache.js";
import messagingService from "./messaging.js"; import messagingService from "./messaging.js";
async function prepareTree(noteRows, branchRows, parentToChildren) { async function prepareTree(noteRows, branchRows, relations) {
utils.assertArguments(noteRows, branchRows, parentToChildren); utils.assertArguments(noteRows, branchRows, relations);
treeCache.load(noteRows, branchRows, parentToChildren); treeCache.load(noteRows, branchRows, relations);
return await prepareRealBranch(await treeCache.getNote('root')); return await prepareRealBranch(await treeCache.getNote('root'));
} }

View file

@ -5,7 +5,7 @@ import infoService from "./info.js";
import server from "./server.js"; import server from "./server.js";
class TreeCache { class TreeCache {
load(noteRows, branchRows, parentToChildren) { load(noteRows, branchRows, relations) {
this.parents = {}; this.parents = {};
this.children = {}; this.children = {};
this.childParentToBranch = {}; this.childParentToBranch = {};
@ -16,10 +16,10 @@ class TreeCache {
/** @type {Object.<string, Branch>} */ /** @type {Object.<string, Branch>} */
this.branches = {}; this.branches = {};
this.addResp(noteRows, branchRows, parentToChildren); this.addResp(noteRows, branchRows, relations);
} }
addResp(noteRows, branchRows, parentToChildren) { addResp(noteRows, branchRows, relations) {
for (const noteRow of noteRows) { for (const noteRow of noteRows) {
const note = new NoteShort(this, noteRow); const note = new NoteShort(this, noteRow);
@ -32,26 +32,33 @@ class TreeCache {
this.addBranch(branch); this.addBranch(branch);
} }
for (const relation of parentToChildren) { for (const relation of relations) {
this.addBranchRelationship(relation.branchId, relation.childNoteId, relation.parentNoteId); this.addBranchRelationship(relation.branchId, relation.childNoteId, relation.parentNoteId);
} }
} }
async getNotes(noteIds) {
const missingNoteIds = noteIds.filter(noteId => this.notes[noteId] === undefined);
if (missingNoteIds.length > 0) {
const resp = await server.post('tree/load', { noteIds: missingNoteIds });
this.addResp(resp.notes, resp.branches, resp.relations);
}
return noteIds.map(noteId => {
if (!this.notes[noteId]) {
throw new Error(`Can't find note ${noteId}`);
}
else {
return this.notes[noteId];
}
});
}
/** @return NoteShort */ /** @return NoteShort */
async getNote(noteId) { async getNote(noteId) {
if (this.notes[noteId] === undefined) { return (await this.getNotes([noteId]))[0];
const resp = await server.post('tree/load', {
noteIds: [noteId]
});
this.addResp(resp.notes, resp.branches, resp.parentToChildren);
}
if (!this.notes[noteId]) {
throw new Error(`Can't find note ${noteId}`);
}
return this.notes[noteId];
} }
addBranch(branch) { addBranch(branch) {
@ -61,12 +68,8 @@ class TreeCache {
} }
addBranchRelationship(branchId, childNoteId, parentNoteId) { addBranchRelationship(branchId, childNoteId, parentNoteId) {
this.addParentChildRelationship(parentNoteId, childNoteId);
this.childParentToBranch[childNoteId + '-' + parentNoteId] = branchId; this.childParentToBranch[childNoteId + '-' + parentNoteId] = branchId;
}
addParentChildRelationship(parentNoteId, childNoteId) {
this.parents[childNoteId] = this.parents[childNoteId] || []; this.parents[childNoteId] = this.parents[childNoteId] || [];
if (!this.parents[childNoteId].includes(parentNoteId)) { if (!this.parents[childNoteId].includes(parentNoteId)) {
@ -86,36 +89,46 @@ class TreeCache {
this.addBranch(branch); this.addBranch(branch);
} }
async getBranches(branchIds) {
const missingBranchIds = branchIds.filter(branchId => this.branches[branchId] === undefined);
if (missingBranchIds.length > 0) {
const resp = await server.post('tree/load', { branchIds: branchIds });
this.addResp(resp.notes, resp.branches, resp.relations);
}
return branchIds.map(branchId => {
if (!this.branches[branchId]) {
throw new Error(`Can't find branch ${branchId}`);
}
else {
return this.branches[branchId];
}
});
}
/** @return Branch */ /** @return Branch */
async getBranch(branchId) { async getBranch(branchId) {
if (this.branches[branchId] === undefined) { return (await this.getBranches([branchId]))[0];
const resp = await server.post('tree/load', {
branchIds: [branchId]
});
this.addResp(resp.notes, resp.branches, resp.parentToChildren);
}
if (!this.branches[branchId]) {
throw new Error(`Can't find branch ${branchId}`);
}
return this.branches[branchId];
} }
/** @return Branch */ /** @return Branch */
async getBranchByChildParent(childNoteId, parentNoteId) { async getBranchByChildParent(childNoteId, parentNoteId) {
// this will make sure the note and its relationships are loaded const branchId = this.getBranchIdByChildParent(childNoteId, parentNoteId);
await this.getNote(parentNoteId);
const key = (childNoteId + '-' + parentNoteId); return await this.getBranch(branchId);
}
getBranchIdByChildParent(childNoteId, parentNoteId) {
const key = childNoteId + '-' + parentNoteId;
const branchId = this.childParentToBranch[key]; const branchId = this.childParentToBranch[key];
if (!branchId) { if (!branchId) {
infoService.throwError("Cannot find branch for child-parent=" + key); infoService.throwError("Cannot find branch for child-parent=" + key);
} }
return await this.getBranch(branchId); return branchId;
} }
/* Move note from one parent to another. */ /* Move note from one parent to another. */

View file

@ -17,7 +17,7 @@ async function getNotes(noteIds) {
return notes; return notes;
} }
async function getParentToChildren(noteIds) { async function getRelations(noteIds) {
const questionMarks = noteIds.map(() => "?").join(","); const questionMarks = noteIds.map(() => "?").join(",");
return await sql.getRows(`SELECT branchId, noteId AS 'childNoteId', parentNoteId FROM branches WHERE isDeleted = 0 return await sql.getRows(`SELECT branchId, noteId AS 'childNoteId', parentNoteId FROM branches WHERE isDeleted = 0
@ -40,13 +40,13 @@ async function getTree() {
const notes = await getNotes(noteIds); const notes = await getNotes(noteIds);
const parentToChildren = await getParentToChildren(noteIds); const relations = await getRelations(noteIds);
return { return {
startNotePath: await optionService.getOption('startNotePath'), startNotePath: await optionService.getOption('startNotePath'),
branches, branches,
notes, notes,
parentToChildren relations
}; };
} }
@ -64,12 +64,12 @@ async function load(req) {
const notes = await getNotes(noteIds); const notes = await getNotes(noteIds);
const parentToChildren = await getParentToChildren(noteIds); const relations = await getRelations(noteIds);
return { return {
branches, branches,
notes, notes,
parentToChildren relations
}; };
} }