Added Types and reformating code

Signed-off-by: Yannick Bungers <git@innay.de>
Signed-off-by: David Mehren <dmehren1@gmail.com>
This commit is contained in:
Yannick Bungers 2020-04-11 14:32:53 +02:00 committed by David Mehren
parent 84e021a0b0
commit de09524658
No known key found for this signature in database
GPG key ID: 6017AF117F9756CB

View file

@ -1,9 +1,9 @@
import {BelongsTo, Column, DataType, ForeignKey, IsUUID, Model, PrimaryKey, Table} from 'sequelize-typescript' import { BelongsTo, Column, DataType, ForeignKey, IsUUID, Model, PrimaryKey, Table } from 'sequelize-typescript'
import {ChildProcess} from "child_process"; import { ChildProcess } from 'child_process'
import {Note} from './note' import { Note } from './note'
import {Utils} from "../utils"; import { Utils } from '../utils'
import Sequelize from "sequelize"; import Sequelize from 'sequelize'
import async = require('async'); import async = require('async');
import moment = require('moment'); import moment = require('moment');
import childProcess = require('child_process'); import childProcess = require('child_process');
@ -12,19 +12,25 @@ import path = require('path');
// core // core
import logger = require('../logger'); import logger = require('../logger');
const Op = Sequelize.Op; const Op = Sequelize.Op
let dmpWorker: ChildProcess | null = createDmpWorker(); const dmpCallbackCache = {}
const dmpCallbackCache = {};
function createDmpWorker() { class Data {
const worker = childProcess.fork(path.resolve(__dirname, '../workers/dmpWorker.js'), ['ignore']); msg;
cacheKey;
error;
result;
}
function createDmpWorker (): ChildProcess {
const worker = childProcess.fork(path.resolve(__dirname, '../workers/dmpWorker.js'), ['ignore'])
logger.debug('dmp worker process started') logger.debug('dmp worker process started')
worker.on('message', function (data: any) { worker.on('message', function (data: Data) {
if (!data || !data.msg || !data.cacheKey) { if (!data || !data.msg || !data.cacheKey) {
return logger.error('dmp worker error: not enough data on message') logger.error('dmp worker error: not enough data on message')
} }
const cacheKey = data.cacheKey; const cacheKey = data.cacheKey
switch (data.msg) { switch (data.msg) {
case 'error': case 'error':
dmpCallbackCache[cacheKey](data.error, null) dmpCallbackCache[cacheKey](data.error, null)
@ -36,15 +42,18 @@ function createDmpWorker() {
delete dmpCallbackCache[cacheKey] delete dmpCallbackCache[cacheKey]
}) })
worker.on('close', function (code) { worker.on('close', function (code) {
dmpWorker = null;
logger.debug(`dmp worker process exited with code ${code}`) logger.debug(`dmp worker process exited with code ${code}`)
}) })
return worker return worker
} }
function sendDmpWorker(data, callback) { let dmpWorker: ChildProcess = createDmpWorker()
if (!dmpWorker) dmpWorker = createDmpWorker()
const cacheKey = Date.now() + '_' + shortId.generate(); function sendDmpWorker (data, callback): void {
if (!dmpWorker?.connected) {
dmpWorker = createDmpWorker()
}
const cacheKey = Date.now() + '_' + shortId.generate()
dmpCallbackCache[cacheKey] = callback dmpCallbackCache[cacheKey] = callback
data = Object.assign(data, { data = Object.assign(data, {
cacheKey: cacheKey cacheKey: cacheKey
@ -59,42 +68,42 @@ export class Revision extends Model<Revision> {
@Column @Column
id: string; id: string;
@Column(DataType.TEXT({length: 'long'})) @Column(DataType.TEXT({ length: 'long' }))
get patch(): string { get patch (): string {
return Utils.processData(this.getDataValue('patch'), '') return Utils.processData(this.getDataValue('patch'), '')
} }
set patch(value: string) { set patch (value: string) {
this.setDataValue('patch', Utils.stripNullByte(value)) this.setDataValue('patch', Utils.stripNullByte(value))
} }
@Column(DataType.TEXT({length: 'long'})) @Column(DataType.TEXT({ length: 'long' }))
get lastContent(): string { get lastContent (): string {
return Utils.processData(this.getDataValue('lastContent'), '') return Utils.processData(this.getDataValue('lastContent'), '')
} }
set lastContent(value: string) { set lastContent (value: string) {
this.setDataValue('lastContent', Utils.stripNullByte(value)) this.setDataValue('lastContent', Utils.stripNullByte(value))
} }
@Column(DataType.TEXT({length: 'long'})) @Column(DataType.TEXT({ length: 'long' }))
get content(): string { get content (): string {
return Utils.processData(this.getDataValue('content'), '') return Utils.processData(this.getDataValue('content'), '')
} }
set content(value: string) { set content (value: string) {
this.setDataValue('content', Utils.stripNullByte(value)) this.setDataValue('content', Utils.stripNullByte(value))
} }
@Column(DataType.INTEGER) @Column(DataType.INTEGER)
length: number length: number
@Column(DataType.TEXT({length: 'long'})) @Column(DataType.TEXT({ length: 'long' }))
get authorship(): string { get authorship (): string {
return Utils.processData(this.getDataValue('authorship'), [], JSON.parse) return Utils.processData(this.getDataValue('authorship'), [], JSON.parse)
} }
set authorship(value: string) { set authorship (value: string) {
this.setDataValue('authorship', value ? JSON.stringify(value) : value) this.setDataValue('authorship', value ? JSON.stringify(value) : value)
} }
@ -102,17 +111,21 @@ export class Revision extends Model<Revision> {
@Column(DataType.UUID) @Column(DataType.UUID)
noteId: string noteId: string
@BelongsTo(() => Note, {foreignKey: 'noteId', constraints: false, onDelete: 'CASCADE', hooks: true}) @BelongsTo(() => Note, { foreignKey: 'noteId', constraints: false, onDelete: 'CASCADE', hooks: true })
note: Note; note: Note;
getNoteRevisions(note, callback) { getNoteRevisions (note: Note, callback): void {
Revision.findAll({ Revision.findAll({
where: { where: {
noteId: note.id noteId: note.id
}, },
order: [['createdAt', 'DESC']] order: [['createdAt', 'DESC']]
}).then(function (revisions) { }).then(function (revisions) {
const data: any[] = []; class RevisionDataActions { // TODO: Fix Type in actions.ts
time;
length
}
const data: RevisionDataActions[] = []
revisions.forEach(function (revision) { revisions.forEach(function (revision) {
data.push({ data.push({
time: moment(revision.createdAt).valueOf(), time: moment(revision.createdAt).valueOf(),
@ -125,7 +138,7 @@ export class Revision extends Model<Revision> {
}) })
} }
getPatchedNoteRevisionByTime(note, time, callback) { getPatchedNoteRevisionByTime (note: Note, time, errorCallback): void {
// find all revisions to prepare for all possible calculation // find all revisions to prepare for all possible calculation
Revision.findAll({ Revision.findAll({
where: { where: {
@ -133,7 +146,9 @@ export class Revision extends Model<Revision> {
}, },
order: [['createdAt', 'DESC']] order: [['createdAt', 'DESC']]
}).then(function (revisions) { }).then(function (revisions) {
if (revisions.length <= 0) return callback(null, null) if (revisions.length <= 0) {
errorCallback(null, null)
}
// measure target revision position // measure target revision position
Revision.count({ Revision.count({
where: { where: {
@ -141,34 +156,38 @@ export class Revision extends Model<Revision> {
createdAt: { createdAt: {
[Op.gte]: time [Op.gte]: time
} }
}, }
}).then(function (count) { }).then(function (count) {
if (count <= 0) return callback(null, null) if (count <= 0) {
errorCallback(null, null)
}
sendDmpWorker({ sendDmpWorker({
msg: 'get revision', msg: 'get revision',
revisions: revisions, revisions: revisions,
count: count count: count
}, callback) }, errorCallback)
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) errorCallback(err, null)
}) })
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) errorCallback(err, null)
}) })
} }
static checkAllNotesRevision(callback) { static checkAllNotesRevision (callback): void {
Revision.saveAllNotesRevision(function (err, notes) { Revision.saveAllNotesRevision(function (err, notes: Note[]) {
if (err) return callback(err, null) if (err) {
callback(err, null)
}
if (!notes || notes.length <= 0) { if (!notes || notes.length <= 0) {
return callback(null, notes) callback(null, notes)
} else { } else {
Revision.checkAllNotesRevision(callback) Revision.checkAllNotesRevision(callback)
} }
}) })
} }
static saveAllNotesRevision(callback) { static saveAllNotesRevision (callback): void {
Note.findAll({ Note.findAll({
// query all notes that need to save for revision // query all notes that need to save for revision
where: { where: {
@ -195,13 +214,15 @@ export class Revision extends Model<Revision> {
] ]
} }
}).then(function (notes: Note[]) { }).then(function (notes: Note[]) {
if (notes.length <= 0) return callback(null, notes) if (notes.length <= 0) {
const savedNotes: Note[] = []; callback(null, notes)
}
const savedNotes: Note[] = []
async.each(notes, function (note: Note, _callback) { async.each(notes, function (note: Note, _callback) {
// revision saving policy: note not been modified for 5 mins or not save for 10 mins // revision saving policy: note not been modified for 5 mins or not save for 10 mins
if (note.lastchangeAt && note.savedAt) { if (note.lastchangeAt && note.savedAt) {
const lastchangeAt = moment(note.lastchangeAt); const lastchangeAt = moment(note.lastchangeAt)
const savedAt = moment(note.savedAt); const savedAt = moment(note.savedAt)
if (moment().isAfter(lastchangeAt.add(5, 'minutes'))) { if (moment().isAfter(lastchangeAt.add(5, 'minutes'))) {
savedNotes.push(note) savedNotes.push(note)
Revision.saveNoteRevision(note, _callback) Revision.saveNoteRevision(note, _callback)
@ -209,7 +230,7 @@ export class Revision extends Model<Revision> {
savedNotes.push(note) savedNotes.push(note)
Revision.saveNoteRevision(note, _callback) Revision.saveNoteRevision(note, _callback)
} else { } else {
return _callback(null, null) _callback(null, null)
} }
} else { } else {
savedNotes.push(note) savedNotes.push(note)
@ -217,59 +238,61 @@ export class Revision extends Model<Revision> {
} }
}, function (err) { }, function (err) {
if (err) { if (err) {
return callback(err, null) callback(err, null)
} }
// return null when no notes need saving at this moment but have delayed tasks to be done // return null when no notes need saving at this moment but have delayed tasks to be done
const result = ((savedNotes.length === 0) && (notes.length > 0)) ? null : savedNotes; const result = ((savedNotes.length === 0) && (notes.length > 0)) ? null : savedNotes
return callback(null, result) callback(null, result)
}) })
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} }
static saveNoteRevision(note : Note, callback) { static saveNoteRevision (note: Note, callback): void {
Revision.findAll({ Revision.findAll({
where: { where: {
noteId: note.id noteId: note.id
}, },
order: [['createdAt', 'DESC']] order: [['createdAt', 'DESC']]
}).then(function (revisions) { }).then(function (revisions: Revision[]) {
if (revisions.length <= 0) { if (revisions.length <= 0) {
// if no revision available // if no revision available
let noteContent = note.content; let noteContent = note.content
if (noteContent.length === 0) { if (noteContent.length === 0) {
noteContent = ''; noteContent = ''
} }
Revision.create({ Revision.create({
noteId: note.id, noteId: note.id,
lastContent: noteContent, lastContent: noteContent,
length: noteContent.length, length: noteContent.length,
authorship: note.authorship authorship: note.authorship
}).then(function (revision) { }).then(function (revision: Revision) {
Revision.finishSaveNoteRevision(note, revision, callback) Revision.finishSaveNoteRevision(note, revision, callback)
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} else { } else {
const latestRevision = revisions[0]; const latestRevision = revisions[0]
const lastContent = latestRevision.content || latestRevision.lastContent; const lastContent = latestRevision.content || latestRevision.lastContent
const content = note.content; const content = note.content
sendDmpWorker({ sendDmpWorker({
msg: 'create patch', msg: 'create patch',
lastDoc: lastContent, lastDoc: lastContent,
currDoc: content currDoc: content
}, function (err, patch) { }, function (err, patch) {
if (err) logger.error('save note revision error', err) if (err) {
logger.error('save note revision error', err)
}
if (!patch) { if (!patch) {
// if patch is empty (means no difference) then just update the latest revision updated time // if patch is empty (means no difference) then just update the latest revision updated time
latestRevision.changed('updatedAt', true) latestRevision.changed('updatedAt', true)
latestRevision.update({ latestRevision.update({
updatedAt: Date.now() updatedAt: Date.now()
}).then(function (revision) { }).then(function (revision: Revision) {
Revision.finishSaveNoteRevision(note, revision, callback) Revision.finishSaveNoteRevision(note, revision, callback)
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} else { } else {
Revision.create({ Revision.create({
@ -278,36 +301,33 @@ export class Revision extends Model<Revision> {
content: note.content, content: note.content,
length: note.content.length, length: note.content.length,
authorship: note.authorship authorship: note.authorship
}).then(function (revision) { }).then(function (revision: Revision) {
// clear last revision content to reduce db size // clear last revision content to reduce db size
latestRevision.update({ latestRevision.update({
content: null content: null
}).then(function () { }).then(function () {
Revision.finishSaveNoteRevision(note, revision, callback) Revision.finishSaveNoteRevision(note, revision, callback)
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} }
}) })
} }
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} }
static finishSaveNoteRevision(note, revision, callback) { static finishSaveNoteRevision (note: Note, revision: Revision, callback): void {
note.update({ note.update({
savedAt: revision.updatedAt savedAt: revision.updatedAt
}).then(function () { }).then(function () {
return callback(null, revision) callback(null, revision)
}).catch(function (err) { }).catch(function (err) {
return callback(err, null) callback(err, null)
}) })
} }
} }