| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | const sql = require('./sql'); | 
					
						
							| 
									
										
										
										
											2021-02-11 22:50:32 +01:00
										 |  |  | const log = require('./log'); | 
					
						
							| 
									
										
										
										
											2021-06-29 22:15:57 +02:00
										 |  |  | const entityChangesService = require('./entity_changes'); | 
					
						
							| 
									
										
										
										
											2019-01-03 23:27:10 +01:00
										 |  |  | const eventService = require('./events'); | 
					
						
							| 
									
										
										
										
											2021-06-29 22:15:57 +02:00
										 |  |  | const entityConstructor = require("../becca/entity_constructor"); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 21:25:15 +01:00
										 |  |  | function updateEntity(entityChange, entityRow, instanceId) { | 
					
						
							| 
									
										
										
										
											2020-03-08 21:59:19 +01:00
										 |  |  |     // can be undefined for options with isSynced=false
 | 
					
						
							| 
									
										
										
										
											2021-08-26 22:10:59 +02:00
										 |  |  |     if (!entityRow) { | 
					
						
							| 
									
										
										
										
											2021-02-11 22:50:32 +01:00
										 |  |  |         if (entityChange.isSynced) { | 
					
						
							|  |  |  |             if (entityChange.isErased) { | 
					
						
							| 
									
										
										
										
											2022-01-09 21:25:15 +01:00
										 |  |  |                 eraseEntity(entityChange, instanceId); | 
					
						
							| 
									
										
										
										
											2021-02-11 22:50:32 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 log.info(`Encountered synced non-erased entity change without entity: ${JSON.stringify(entityChange)}`); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (entityChange.entityName !== 'options') { | 
					
						
							|  |  |  |             log.info(`Encountered unsynced non-option entity change without entity: ${JSON.stringify(entityChange)}`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-03-08 21:59:19 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:47:33 +01:00
										 |  |  |     const updated = entityChange.entityName === 'note_reordering' | 
					
						
							| 
									
										
										
										
											2022-01-09 21:25:15 +01:00
										 |  |  |         ? updateNoteReordering(entityChange, entityRow, instanceId) | 
					
						
							|  |  |  |         : updateNormalEntity(entityChange, entityRow, instanceId); | 
					
						
							| 
									
										
										
										
											2019-01-03 23:27:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 20:19:44 +02:00
										 |  |  |     if (updated) { | 
					
						
							| 
									
										
										
										
											2021-08-26 22:10:59 +02:00
										 |  |  |         if (entityRow.isDeleted) { | 
					
						
							| 
									
										
										
										
											2021-05-01 11:38:20 +02:00
										 |  |  |             eventService.emit(eventService.ENTITY_DELETE_SYNCED, { | 
					
						
							|  |  |  |                 entityName: entityChange.entityName, | 
					
						
							|  |  |  |                 entityId: entityChange.entityId | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-22 20:19:44 +02:00
										 |  |  |         else if (!entityChange.isErased) { | 
					
						
							| 
									
										
										
										
											2021-05-01 11:38:20 +02:00
										 |  |  |             eventService.emit(eventService.ENTITY_CHANGE_SYNCED, { | 
					
						
							|  |  |  |                 entityName: entityChange.entityName, | 
					
						
							| 
									
										
										
										
											2021-08-26 22:10:59 +02:00
										 |  |  |                 entityRow | 
					
						
							| 
									
										
										
										
											2021-05-01 11:38:20 +02:00
										 |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-01-03 23:27:10 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-04-07 22:25:28 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 10:22:50 +01:00
										 |  |  | function updateNormalEntity(remoteEntityChange, remoteEntityRow, instanceId) { | 
					
						
							| 
									
										
										
										
											2021-01-14 23:22:13 +01:00
										 |  |  |     const localEntityChange = sql.getRow(`
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  |         SELECT utcDateChanged, hash, isErased | 
					
						
							| 
									
										
										
										
											2020-12-14 13:15:32 +01:00
										 |  |  |         FROM entity_changes  | 
					
						
							| 
									
										
										
										
											2021-01-14 23:22:13 +01:00
										 |  |  |         WHERE entityName = ? AND entityId = ?`, [remoteEntityChange.entityName, remoteEntityChange.entityId]);
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:15:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 23:22:13 +01:00
										 |  |  |     if (localEntityChange && !localEntityChange.isErased && remoteEntityChange.isErased) { | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  |         sql.transactional(() => { | 
					
						
							| 
									
										
										
										
											2021-03-23 22:18:23 +01:00
										 |  |  |             const primaryKey = entityConstructor.getEntityFromEntityName(remoteEntityChange.entityName).primaryKeyName; | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 23:22:13 +01:00
										 |  |  |             sql.execute(`DELETE FROM ${remoteEntityChange.entityName} WHERE ${primaryKey} = ?`, remoteEntityChange.entityId); | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 09:53:25 +01:00
										 |  |  |             entityChangesService.addEntityChangeWithInstanceId(remoteEntityChange, instanceId); | 
					
						
							| 
									
										
										
										
											2020-12-14 13:58:02 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 23:22:13 +01:00
										 |  |  |     if (!localEntityChange | 
					
						
							|  |  |  |         || localEntityChange.utcDateChanged < remoteEntityChange.utcDateChanged | 
					
						
							|  |  |  |         || localEntityChange.hash !== remoteEntityChange.hash // sync error, we should still update
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:15:32 +01:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2023-03-08 09:01:23 +01:00
										 |  |  |         if (['note_contents', 'note_revision_contents', 'note_ancillary_contents'].includes(remoteEntityChange.entityName)) { | 
					
						
							| 
									
										
										
										
											2022-12-27 10:22:50 +01:00
										 |  |  |             remoteEntityRow.content = handleContent(remoteEntityRow.content); | 
					
						
							| 
									
										
										
										
											2017-11-28 17:04:47 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-11-01 20:00:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |         sql.transactional(() => { | 
					
						
							| 
									
										
										
										
											2022-12-27 10:22:50 +01:00
										 |  |  |             sql.replace(remoteEntityChange.entityName, remoteEntityRow); | 
					
						
							| 
									
										
										
										
											2019-11-01 20:00:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 09:53:25 +01:00
										 |  |  |             entityChangesService.addEntityChangeWithInstanceId(remoteEntityChange, instanceId); | 
					
						
							| 
									
										
										
										
											2020-04-04 14:57:19 +02:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-11-01 20:00:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-04 14:57:19 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-11-01 20:00:56 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 21:25:15 +01:00
										 |  |  | function updateNoteReordering(entityChange, entity, instanceId) { | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  |     sql.transactional(() => { | 
					
						
							| 
									
										
										
										
											2020-12-14 13:15:32 +01:00
										 |  |  |         for (const key in entity) { | 
					
						
							|  |  |  |             sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity[key], key]); | 
					
						
							| 
									
										
										
										
											2019-10-31 21:58:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 09:53:25 +01:00
										 |  |  |         entityChangesService.addEntityChangeWithInstanceId(entityChange, instanceId); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-04 14:57:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:47:33 +01:00
										 |  |  | function handleContent(content) { | 
					
						
							| 
									
										
										
										
											2022-12-27 10:22:50 +01:00
										 |  |  |     // we always use Buffer object which is different from normal saving - there we use simple string type for
 | 
					
						
							|  |  |  |     // "string notes". The problem is that in general it's not possible to detect whether a note_content
 | 
					
						
							|  |  |  |     // is string note or note (syncs can arrive out of order)
 | 
					
						
							| 
									
										
										
										
											2020-12-14 13:47:33 +01:00
										 |  |  |     content = content === null ? null : Buffer.from(content, 'base64'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (content && content.byteLength === 0) { | 
					
						
							|  |  |  |         // there seems to be a bug which causes empty buffer to be stored as NULL which is then picked up as inconsistency
 | 
					
						
							|  |  |  |         content = ""; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return content; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 21:25:15 +01:00
										 |  |  | function eraseEntity(entityChange, instanceId) { | 
					
						
							| 
									
										
										
										
											2021-11-12 21:19:23 +01:00
										 |  |  |     const {entityName, entityId} = entityChange; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-22 23:36:05 +01:00
										 |  |  |     const entityNames = [ | 
					
						
							|  |  |  |         "notes", | 
					
						
							|  |  |  |         "note_contents", | 
					
						
							|  |  |  |         "branches", | 
					
						
							|  |  |  |         "attributes", | 
					
						
							|  |  |  |         "note_revisions", | 
					
						
							| 
									
										
										
										
											2023-03-08 09:01:23 +01:00
										 |  |  |         "note_revision_contents", | 
					
						
							|  |  |  |         "note_ancillaries", | 
					
						
							|  |  |  |         "note_ancillary_contents" | 
					
						
							| 
									
										
										
										
											2023-01-22 23:36:05 +01:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!entityNames.includes(entityName)) { | 
					
						
							| 
									
										
										
										
											2022-12-27 10:22:50 +01:00
										 |  |  |         log.error(`Cannot erase entity '${entityName}', id '${entityId}'`); | 
					
						
							| 
									
										
										
										
											2021-11-12 21:19:23 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const keyName = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sql.execute(`DELETE FROM ${entityName} WHERE ${keyName} = ?`, [entityId]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     eventService.emit(eventService.ENTITY_DELETE_SYNCED, { entityName, entityId }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 09:53:25 +01:00
										 |  |  |     entityChangesService.addEntityChangeWithInstanceId(entityChange, instanceId); | 
					
						
							| 
									
										
										
										
											2021-11-12 21:19:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | module.exports = { | 
					
						
							| 
									
										
										
										
											2018-04-07 22:32:46 -04:00
										 |  |  |     updateEntity | 
					
						
							| 
									
										
										
										
											2020-06-20 12:31:38 +02:00
										 |  |  | }; |