From bcfe097dd61931ddd29fccddf918f421742ea134 Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 8 May 2021 21:10:58 +0200 Subject: [PATCH] refactoring of becca entity saving --- .../becca/entities/abstract_entity.js | 75 ++++++++++++++++--- src/services/becca/entities/attribute.js | 49 ++++++------ src/services/becca/entities/branch.js | 52 +++++-------- src/services/becca/entities/note.js | 32 +++----- 4 files changed, 116 insertions(+), 92 deletions(-) diff --git a/src/services/becca/entities/abstract_entity.js b/src/services/becca/entities/abstract_entity.js index 45b0e33b0..7630904ff 100644 --- a/src/services/becca/entities/abstract_entity.js +++ b/src/services/becca/entities/abstract_entity.js @@ -1,9 +1,12 @@ "use strict"; const utils = require('../../utils'); +const sql = require('../../sql'); +const entityChangesService = require('../../entity_changes'); +const eventService = require("../../events.js"); +const cls = require("../../cls.js"); let becca = null; -let repo = null; class AbstractEntity { beforeSaving() { @@ -16,13 +19,17 @@ class AbstractEntity { } } - generateHash() { + generateHash(isDeleted = false) { let contentToHash = ""; for (const propertyName of this.constructor.hashedProperties) { contentToHash += "|" + this[propertyName]; } + if (isDeleted) { + contentToHash += "|deleted"; + } + return utils.hash(contentToHash).substr(0, 10); } @@ -39,20 +46,68 @@ class AbstractEntity { return becca; } - // temporarily needed for saving entities - get repository() { - if (!repo) { - repo = require('../../repository'); - } - - return repo; + addEntityChange(isDeleted = false) { + entityChangesService.addEntityChange({ + entityName: this.constructor.entityName, + entityId: this[this.constructor.primaryKeyName], + hash: this.generateHash(isDeleted), + isErased: false, + utcDateChanged: this.getUtcDateChanged(), + isSynced: this.constructor.entityName !== 'options' || !!this.isSynced + }); } save() { - this.repository.updateEntity(this); + const entityName = this.constructor.entityName; + const primaryKeyName = this.constructor.primaryKeyName; + + const isNewEntity = !this[primaryKeyName]; + + if (this.beforeSaving) { + this.beforeSaving(); + } + + const pojo = this.getPojo(); + + sql.transactional(() => { + sql.upsert(entityName, primaryKeyName, pojo); + + if (entityName === 'recent_notes') { + return; + } + + this.addEntityChange(false); + + if (!cls.isEntityEventsDisabled()) { + const eventPayload = { + entityName, + entity: this + }; + + if (isNewEntity) { + eventService.emit(eventService.ENTITY_CREATED, eventPayload); + } + + eventService.emit(eventService.ENTITY_CHANGED, eventPayload); + } + }); return this; } + + markAsDeleted(deleteId = null) { + sql.execute(`UPDATE ${this.constructor.entityName} SET isDeleted = 1, deleteId = ? WHERE ${this.constructor.primaryKeyName} = ?`, + [deleteId, this[this.constructor.primaryKeyName]]); + + this.addEntityChange(true); + + const eventPayload = { + entityName: this.constructor.entityName, + entity: this + }; + + eventService.emit(eventService.ENTITY_DELETED, eventPayload); + } } module.exports = AbstractEntity; diff --git a/src/services/becca/entities/attribute.js b/src/services/becca/entities/attribute.js index 14eb6c606..4d1c87235 100644 --- a/src/services/becca/entities/attribute.js +++ b/src/services/becca/entities/attribute.js @@ -111,6 +111,28 @@ class Attribute extends AbstractEntity { } } + beforeSaving() { + if (!this.value) { + if (this.type === 'relation') { + throw new Error(`Cannot save relation ${this.name} since it does not target any note.`); + } + + // null value isn't allowed + this.value = ""; + } + + if (this.position === undefined) { + // TODO: can be calculated from becca + this.position = 1 + sql.getValue(`SELECT COALESCE(MAX(position), 0) FROM attributes WHERE noteId = ?`, [this.noteId]); + } + + if (!this.isInheritable) { + this.isInheritable = false; + } + + super.beforeSaving(); + } + getPojo() { return { attributeId: this.attributeId, @@ -125,27 +147,6 @@ class Attribute extends AbstractEntity { }; } - beforeSaving() { - if (!this.value) { - if (this.type === 'relation') { - throw new Error(`Cannot save relation ${this.name} since it does not target any note.`); - } - - // null value isn't allowed - this.value = ""; - } - - if (this.position === undefined) { - this.position = 1 + sql.getValue(`SELECT COALESCE(MAX(position), 0) FROM attributes WHERE noteId = ?`, [this.noteId]); - } - - if (!this.isInheritable) { - this.isInheritable = false; - } - - super.beforeSaving(); - } - createClone(type, name, value, isInheritable) { return new Attribute({ noteId: this.noteId, @@ -157,12 +158,6 @@ class Attribute extends AbstractEntity { utcDateModified: this.utcDateModified }); } - - markAsDeleted(deleteId = null) { - sql.execute("UPDATE attributes SET isDeleted = 1, deleteId = ? WHERE attributeId = ?", [deleteId, this.attributeId]); - - // FIXME: this needs to be published into entity_changes (for sync and becca cleanup) - } } module.exports = Attribute; diff --git a/src/services/becca/entities/branch.js b/src/services/becca/entities/branch.js index 24895aa95..d814d3c8d 100644 --- a/src/services/becca/entities/branch.js +++ b/src/services/becca/entities/branch.js @@ -67,25 +67,34 @@ class Branch extends AbstractEntity { return this.becca.notes[this.parentNoteId]; } + beforeSaving() { + if (this.notePosition === undefined || this.notePosition === null) { + // TODO finding new position can be refactored into becca + const maxNotePos = sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]); + this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10; + } + + if (!this.isExpanded) { + this.isExpanded = false; + } + + this.utcDateModified = dateUtils.utcNowDateTime(); + + super.beforeSaving(); + } + getPojo() { - const pojo = { + return { branchId: this.branchId, noteId: this.noteId, parentNoteId: this.parentNoteId, prefix: this.prefix, notePosition: this.notePosition, isExpanded: this.isExpanded, - utcDateModified: dateUtils.utcNowDateTime() + utcDateModified: this.utcDateModified, + // not used for anything, will be later dropped + utcDateCreated: dateUtils.utcNowDateTime() }; - - // FIXME - if (true || !pojo.branchId) { - pojo.utcDateCreated = dateUtils.utcNowDateTime(); - } - - this.utcDateModified = dateUtils.utcNowDateTime(); - - return pojo; } createClone(parentNoteId, notePosition) { @@ -97,27 +106,6 @@ class Branch extends AbstractEntity { isExpanded: this.isExpanded }); } - - beforeSaving() { - // TODO can be refactored into becca - if (this.notePosition === undefined || this.notePosition === null) { - const maxNotePos = sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]); - this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10; - } - - if (!this.isExpanded) { - this.isExpanded = false; - } - - super.beforeSaving(); - } - - markAsDeleted(deleteId = null) { - sql.execute("UPDATE branches SET isDeleted = 1, deleteId = ? WHERE branchId = ?", - [deleteId, this.branchId]); - - // FIXME: this needs to be published into entity_changes (for sync and becca cleanup) - } } module.exports = Branch; diff --git a/src/services/becca/entities/note.js b/src/services/becca/entities/note.js index 565e5c759..0c74292e4 100644 --- a/src/services/becca/entities/note.js +++ b/src/services/becca/entities/note.js @@ -68,11 +68,11 @@ class Note extends AbstractEntity { /** @param {string} */ this.mime = row.mime; /** @param {string} */ - this.dateCreated = row.dateCreated; + this.dateCreated = row.dateCreated || dateUtils.localNowDateTime(); /** @param {string} */ this.dateModified = row.dateModified; /** @param {string} */ - this.utcDateCreated = row.utcDateCreated; + this.utcDateCreated = row.utcDateCreated || dateUtils.utcNowDateTime(); /** @param {string} */ this.utcDateModified = row.utcDateModified; @@ -823,6 +823,13 @@ class Note extends AbstractEntity { } } + beforeSaving() { + super.beforeSaving(); + + this.dateModified = dateUtils.localNowDateTime(); + this.utcDateModified = dateUtils.utcNowDateTime(); + } + getPojo() { const pojo = { noteId: this.noteId, @@ -848,27 +855,6 @@ class Note extends AbstractEntity { return pojo; } - - beforeSaving() { - if (!this.dateCreated) { - this.dateCreated = dateUtils.localNowDateTime(); - } - - if (!this.utcDateCreated) { - this.utcDateCreated = dateUtils.utcNowDateTime(); - } - - super.beforeSaving(); - - this.dateModified = dateUtils.localNowDateTime(); - this.utcDateModified = dateUtils.utcNowDateTime(); - } - - markAsDeleted(deleteId = null) { - sql.execute("UPDATE notes SET isDeleted = 1, deleteId = ? WHERE noteId = ?", [deleteId, this.noteId]); - - // FIXME: this needs to be published into entity_changes (for sync and becca cleanup) - } } module.exports = Note;