refactoring of becca entity saving

This commit is contained in:
zadam 2021-05-08 21:10:58 +02:00
parent 2edc7dbf58
commit bcfe097dd6
4 changed files with 116 additions and 92 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;