simplification of tree cache

This commit is contained in:
zadam
2019-10-26 09:51:08 +02:00
parent 22d48b0586
commit ed9ecf2a57
10 changed files with 159 additions and 172 deletions

View File

@@ -1,7 +1,6 @@
import utils from "./utils.js";
import Branch from "../entities/branch.js";
import NoteShort from "../entities/note_short.js";
import toastService from "./toast.js";
import ws from "./ws.js";
import server from "./server.js";
@@ -14,14 +13,6 @@ class TreeCache {
}
init() {
/** @type {Object.<string, string>} */
this.parents = {};
/** @type {Object.<string, string>} */
this.children = {};
/** @type {Object.<string, string>} */
this.childParentToBranch = {};
/** @type {Object.<string, NoteShort>} */
this.notes = {};
@@ -36,58 +27,88 @@ class TreeCache {
}
addResp(noteRows, branchRows) {
for (const noteRow of noteRows) {
const note = new NoteShort(this, noteRow);
this.notes[note.noteId] = note;
}
const branchesByNotes = {};
for (const branchRow of branchRows) {
const branch = new Branch(this, branchRow);
this.addBranch(branch);
branchesByNotes[branch.noteId] = branchesByNotes[branch.noteId] || [];
branchesByNotes[branch.noteId].push(branch);
branchesByNotes[branch.parentNoteId] = branchesByNotes[branch.parentNoteId] || [];
branchesByNotes[branch.parentNoteId].push(branch);
}
for (const noteRow of noteRows) {
const {noteId} = noteRow;
const oldNote = this.notes[noteId];
if (oldNote) {
for (const childNoteId of oldNote.children) {
const childNote = this.notes[childNoteId];
if (childNote) {
childNote.parents = childNote.parents.filter(p => p !== noteId);
const branchId = childNote.parentToBranch[noteId];
if (branchId in this.branches) {
delete this.branches[branchId];
}
delete childNote.parentToBranch[noteId];
}
}
for (const parentNoteId of oldNote.parents) {
const parentNote = this.notes[parentNoteId];
if (parentNote) {
parentNote.children = parentNote.children.filter(p => p !== noteId);
const branchId = parentNote.childToBranch[noteId];
if (branchId in this.branches) {
delete this.branches[branchId];
}
delete parentNote.childToBranch[noteId];
}
}
}
const note = new NoteShort(this, noteRow, branchesByNotes[noteId]);
this.notes[note.noteId] = note;
for (const childNoteId of note.children) {
const childNote = this.notes[childNoteId];
if (childNote) {
childNote.addParent(noteId, note.childToBranch[childNoteId]);
}
}
for (const parentNoteId of note.parents) {
const parentNote = this.notes[parentNoteId];
if (parentNote) {
parentNote.addChild(noteId, note.parentToBranch[parentNoteId]);
}
}
}
}
/**
* Reload notes and their children.
*/
async reloadNotesAndTheirChildren(noteIds) {
async reloadNotes(noteIds) {
// first load the data before clearing the cache
const resp = await server.post('tree/load', { noteIds });
for (const noteId of noteIds) {
for (const childNoteId of this.children[noteId] || []) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
delete this.branches[branchId];
delete this.childParentToBranch[childNoteId + '-' + noteId];
}
this.children[noteId] = [];
delete this.notes[noteId];
}
this.addResp(resp.notes, resp.branches);
}
/**
* Reloads parents of given noteId - useful when new note is created to make sure note is loaded
* in a correct order.
*/
async reloadParents(noteId) {
// to be able to find parents we need first to make sure it is actually loaded
await this.getNote(noteId);
await this.reloadNotesAndTheirChildren(this.parents[noteId] || []);
// this is done to load the new parents for the noteId
await this.reloadNotesAndTheirChildren([noteId]);
}
/** @return {Promise<NoteShort[]>} */
async getNotes(noteIds, silentNotFoundError = false) {
const missingNoteIds = noteIds.filter(noteId => this.notes[noteId] === undefined);
@@ -128,34 +149,6 @@ class TreeCache {
addBranch(branch) {
this.branches[branch.branchId] = branch;
this.addBranchRelationship(branch.branchId, branch.noteId, branch.parentNoteId);
}
addBranchRelationship(branchId, childNoteId, parentNoteId) {
if (parentNoteId === 'none') { // applies only to root element
return;
}
this.childParentToBranch[childNoteId + '-' + parentNoteId] = branchId;
this.parents[childNoteId] = this.parents[childNoteId] || [];
if (!this.parents[childNoteId].includes(parentNoteId)) {
this.parents[childNoteId].push(parentNoteId);
}
this.children[parentNoteId] = this.children[parentNoteId] || [];
if (!this.children[parentNoteId].includes(childNoteId)) {
this.children[parentNoteId].push(childNoteId);
}
}
add(note, branch) {
this.notes[note.noteId] = note;
this.addBranch(branch);
}
async getBranches(branchIds) {
@@ -181,60 +174,6 @@ class TreeCache {
async getBranch(branchId) {
return (await this.getBranches([branchId]))[0];
}
/** @return Branch */
async getBranchByChildParent(childNoteId, parentNoteId) {
const branchId = this.getBranchIdByChildParent(childNoteId, parentNoteId);
return await this.getBranch(branchId);
}
getBranchIdByChildParent(childNoteId, parentNoteId) {
const key = childNoteId + '-' + parentNoteId;
const branchId = this.childParentToBranch[key];
if (!branchId) {
toastService.throwError("Cannot find branch for child-parent=" + key);
}
return branchId;
}
/* Move note from one parent to another. */
async moveNote(childNoteId, oldParentNoteId, newParentNoteId, beforeNoteId, afterNoteId) {
utils.assertArguments(childNoteId, oldParentNoteId, newParentNoteId);
if (oldParentNoteId === newParentNoteId) {
return;
}
const branchId = this.childParentToBranch[childNoteId + '-' + oldParentNoteId];
const branch = await this.getBranch(branchId);
branch.parentNoteId = newParentNoteId;
this.childParentToBranch[childNoteId + '-' + newParentNoteId] = branchId;
delete this.childParentToBranch[childNoteId + '-' + oldParentNoteId]; // this is correct because we know that oldParentId isn't same as newParentId
// remove old associations
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== oldParentNoteId);
this.children[oldParentNoteId] = this.children[oldParentNoteId].filter(ch => ch !== childNoteId);
// add new associations
this.parents[childNoteId].push(newParentNoteId);
const children = this.children[newParentNoteId] = this.children[newParentNoteId] || []; // this might be first child
// we try to put the note into precise order which might be used again by lazy-loaded nodes
if (beforeNoteId && children.includes(beforeNoteId)) {
children.splice(children.indexOf(beforeNoteId), 0, childNoteId);
}
else if (afterNoteId && children.includes(afterNoteId)) {
children.splice(children.indexOf(afterNoteId) + 1, 0, childNoteId);
}
else {
children.push(childNoteId);
}
}
}
const treeCache = new TreeCache();