updating becca after sync

This commit is contained in:
zadam 2021-08-07 21:21:30 +02:00
parent 669eaa7509
commit 86a53ceebb
8 changed files with 103 additions and 42 deletions

View File

@ -102,6 +102,10 @@ class Becca {
return null; return null;
} }
if (entityName === 'note_revisions') {
return this.getNoteRevision(entityId);
}
const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g, const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g,
group => group =>
group group

View File

@ -1,15 +1,16 @@
"use strict"; "use strict";
const sql = require('../services/sql.js'); const sql = require('../services/sql');
const eventService = require('../services/events.js'); const eventService = require('../services/events');
const becca = require('./becca.js'); const becca = require('./becca');
const sqlInit = require('../services/sql_init'); const sqlInit = require('../services/sql_init');
const log = require('../services/log'); const log = require('../services/log');
const Note = require('./entities/note.js'); const Note = require('./entities/note');
const Branch = require('./entities/branch.js'); const Branch = require('./entities/branch');
const Attribute = require('./entities/attribute.js'); const Attribute = require('./entities/attribute');
const Option = require('./entities/option.js'); const Option = require('./entities/option');
const cls = require("../services/cls.js"); const cls = require("../services/cls");
const entityConstructor = require("../becca/entity_constructor");
const beccaLoaded = new Promise((res, rej) => { const beccaLoaded = new Promise((res, rej) => {
sqlInit.dbReady.then(() => { sqlInit.dbReady.then(() => {
@ -49,11 +50,7 @@ function load() {
log.info(`Becca (note cache) load took ${Date.now() - start}ms`); log.info(`Becca (note cache) load took ${Date.now() - start}ms`);
} }
eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_CHANGE_SYNCED], ({entityName, entity}) => { function postProcessEntityUpdate(entityName, entity) {
if (!becca.loaded) {
return;
}
if (entityName === 'branches') { if (entityName === 'branches') {
branchUpdated(entity); branchUpdated(entity);
} else if (entityName === 'attributes') { } else if (entityName === 'attributes') {
@ -61,6 +58,37 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_CHANGE_
} else if (entityName === 'note_reordering') { } else if (entityName === 'note_reordering') {
noteReorderingUpdated(entity); noteReorderingUpdated(entity);
} }
}
eventService.subscribe([eventService.ENTITY_CHANGE_SYNCED], ({entityName, entity}) => {
if (!becca.loaded) {
return;
}
if (["notes", "branches", "attributes"].includes(entityName)) {
const EntityClass = entityConstructor.getEntityFromEntityName(entityName);
const primaryKeyName = EntityClass.primaryKeyName;
let entity = becca.getEntity(entityName, entity[primaryKeyName]);
if (entity) {
entity.updateFromRow(entity);
} else {
entity = new EntityClass();
entity.updateFromRow(entity);
entity.init();
}
}
postProcessEntityUpdate(entityName, entity);
});
eventService.subscribe(eventService.ENTITY_CHANGED, ({entityName, entity}) => {
if (!becca.loaded) {
return;
}
postProcessEntityUpdate(entityName, entity);
}); });
eventService.subscribe([eventService.ENTITY_DELETED, eventService.ENTITY_DELETE_SYNCED], ({entityName, entityId}) => { eventService.subscribe([eventService.ENTITY_DELETED, eventService.ENTITY_DELETE_SYNCED], ({entityName, entityId}) => {

View File

@ -18,6 +18,11 @@ class Attribute extends AbstractEntity {
return; return;
} }
this.updateFromRow(row);
this.init();
}
updateFromRow(row) {
this.update([ this.update([
row.attributeId, row.attributeId,
row.noteId, row.noteId,
@ -28,8 +33,6 @@ class Attribute extends AbstractEntity {
row.position, row.position,
row.utcDateModified row.utcDateModified
]); ]);
this.init();
} }
update([attributeId, noteId, type, name, value, isInheritable, position, utcDateModified]) { update([attributeId, noteId, type, name, value, isInheritable, position, utcDateModified]) {

View File

@ -18,6 +18,11 @@ class Branch extends AbstractEntity {
return; return;
} }
this.updateFromRow(row);
this.init();
}
updateFromRow(row) {
this.update([ this.update([
row.branchId, row.branchId,
row.noteId, row.noteId,
@ -27,8 +32,6 @@ class Branch extends AbstractEntity {
row.isExpanded, row.isExpanded,
row.utcDateModified row.utcDateModified
]); ]);
this.init();
} }
update([branchId, noteId, parentNoteId, prefix, notePosition, isExpanded, utcDateModified]) { update([branchId, noteId, parentNoteId, prefix, notePosition, isExpanded, utcDateModified]) {

View File

@ -24,6 +24,11 @@ class Note extends AbstractEntity {
return; return;
} }
this.updateFromRow(row);
this.init();
}
updateFromRow(row) {
this.update([ this.update([
row.noteId, row.noteId,
row.title, row.title,
@ -35,8 +40,6 @@ class Note extends AbstractEntity {
row.utcDateCreated, row.utcDateCreated,
row.utcDateModified row.utcDateModified
]); ]);
this.init();
} }
update([noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified]) { update([noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified]) {
@ -198,7 +201,7 @@ class Note extends AbstractEntity {
return JSON.parse(content); return JSON.parse(content);
} }
setContent(content) { setContent(content, ignoreMissingProtectedSession = false) {
if (content === null || content === undefined) { if (content === null || content === undefined) {
throw new Error(`Cannot set null content to note ${this.noteId}`); throw new Error(`Cannot set null content to note ${this.noteId}`);
} }
@ -221,7 +224,7 @@ class Note extends AbstractEntity {
if (protectedSessionService.isProtectedSessionAvailable()) { if (protectedSessionService.isProtectedSessionAvailable()) {
pojo.content = protectedSessionService.encrypt(pojo.content); pojo.content = protectedSessionService.encrypt(pojo.content);
} }
else { else if (!ignoreMissingProtectedSession) {
throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`); throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`);
} }
} }

View File

@ -108,7 +108,7 @@ class NoteRevision extends AbstractEntity {
} }
} }
setContent(content) { setContent(content, ignoreMissingProtectedSession = false) {
const pojo = { const pojo = {
noteRevisionId: this.noteRevisionId, noteRevisionId: this.noteRevisionId,
content: content, content: content,
@ -119,14 +119,14 @@ class NoteRevision extends AbstractEntity {
if (protectedSessionService.isProtectedSessionAvailable()) { if (protectedSessionService.isProtectedSessionAvailable()) {
pojo.content = protectedSessionService.encrypt(pojo.content); pojo.content = protectedSessionService.encrypt(pojo.content);
} }
else { else if (!ignoreMissingProtectedSession) {
throw new Error(`Cannot update content of noteRevisionId=${this.noteRevisionId} since we're out of protected session.`); throw new Error(`Cannot update content of noteRevisionId=${this.noteRevisionId} since we're out of protected session.`);
} }
} }
sql.upsert("note_revision_contents", "noteRevisionId", pojo); sql.upsert("note_revision_contents", "noteRevisionId", pojo);
const hash = utils.hash(this.noteRevisionId + "|" + content); const hash = utils.hash(this.noteRevisionId + "|" + pojo.content.toString());
entityChangesService.addEntityChange({ entityChangesService.addEntityChange({
entityName: 'note_revision_contents', entityName: 'note_revision_contents',
@ -138,6 +138,17 @@ class NoteRevision extends AbstractEntity {
}); });
} }
/** @returns {{contentLength, dateModified, utcDateModified}} */
getContentMetadata() {
return sql.getRow(`
SELECT
LENGTH(content) AS contentLength,
dateModified,
utcDateModified
FROM note_revision_contents
WHERE noteRevisionId = ?`, [this.noteRevisionId]);
}
beforeSaving() { beforeSaving() {
super.beforeSaving(); super.beforeSaving();

View File

@ -460,26 +460,35 @@ class ConsistencyChecks {
runEntityChangeChecks(entityName, key) { runEntityChangeChecks(entityName, key) {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT SELECT
${key} as entityId ${key} as entityId
FROM FROM
${entityName} ${entityName}
LEFT JOIN entity_changes ON entity_changes.entityName = '${entityName}' LEFT JOIN entity_changes ON entity_changes.entityName = '${entityName}'
AND entity_changes.entityId = ${key} AND entity_changes.entityId = ${key}
WHERE WHERE
entity_changes.id IS NULL`, entity_changes.id IS NULL`,
({entityId}) => { ({entityId}) => {
if (this.autoFix) { if (this.autoFix) {
const entity = becca.getEntity(entityName, entityId); if (entityName === 'note_contents' || entityName === 'note_revision_contents') {
const entity = entityName === 'note_contents'
? becca.getNote(entityId)
: becca.getNoteRevision(entityId);
entityChangesService.addEntityChange({ entity.setContent(entity.getContent(), true);
entityName, }
entityId, else {
hash: entity.generateHash(), const entity = becca.getEntity(entityName, entityId);
isErased: false,
utcDateChanged: entity.getUtcDateChanged(), entityChangesService.addEntityChange({
isSynced: entityName !== 'options' || entity.isSynced entityName,
}); entityId,
hash: entity.generateHash(),
isErased: false,
utcDateChanged: entity.getUtcDateChanged(),
isSynced: entityName !== 'options' || entity.isSynced
});
}
logFix(`Created missing entity change for entityName=${entityName}, entityId=${entityId}`); logFix(`Created missing entity change for entityName=${entityName}, entityId=${entityId}`);
} else { } else {

View File

@ -124,7 +124,7 @@ function processInverseRelations(entityName, entity, handler) {
eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => { eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => {
processInverseRelations(entityName, entity, (definition, note, targetNote) => { processInverseRelations(entityName, entity, (definition, note, targetNote) => {
// we need to make sure that also target's inverse attribute exists and if note, then create it // we need to make sure that also target's inverse attribute exists and if not, then create it
// inverse attribute has to target our note as well // inverse attribute has to target our note as well
const hasInverseAttribute = (targetNote.getRelations(definition.inverseRelation)) const hasInverseAttribute = (targetNote.getRelations(definition.inverseRelation))
.some(attr => attr.value === note.noteId); .some(attr => attr.value === note.noteId);