feat: page cache + save/load logic + db fixes

This commit is contained in:
Nicolas Giard
2018-09-15 20:58:23 -04:00
parent 572393aa7b
commit 2c6a95f900
9 changed files with 159 additions and 66 deletions

View File

@@ -16,6 +16,7 @@ module.exports = class PageHistory extends Model {
properties: {
id: {type: 'integer'},
path: {type: 'string'},
hash: {type: 'string'},
title: {type: 'string'},
description: {type: 'string'},
isPublished: {type: 'boolean'},
@@ -88,6 +89,7 @@ module.exports = class PageHistory extends Model {
content: opts.content,
description: opts.description,
editorKey: opts.editorKey,
hash: opts.hash,
isPrivate: opts.isPrivate,
isPublished: opts.isPublished,
localeCode: opts.localeCode,

View File

@@ -1,5 +1,9 @@
const Model = require('objection').Model
const _ = require('lodash')
const JSBinType = require('js-binary').Type
const pageHelper = require('../helpers/page')
const path = require('path')
const fs = require('fs-extra')
/* global WIKI */
@@ -17,6 +21,7 @@ module.exports = class Page extends Model {
properties: {
id: {type: 'integer'},
path: {type: 'string'},
hash: {type: 'string'},
title: {type: 'string'},
description: {type: 'string'},
isPublished: {type: 'boolean'},
@@ -89,35 +94,33 @@ module.exports = class Page extends Model {
this.updatedAt = new Date().toISOString()
}
static async getPage(opts) {
const page = await WIKI.models.pages.query().where({
path: opts.path,
localeCode: opts.locale
}).andWhere(builder => {
builder.where({
isPublished: true
}).orWhere({
isPublished: false,
authorId: opts.userId
})
}).andWhere(builder => {
if (opts.private) {
builder.where({ isPrivate: true, privateNS: opts.privateNS })
} else {
builder.where({ isPrivate: false })
}
}).first()
return page
static get cacheSchema() {
return new JSBinType({
authorId: 'uint',
authorName: 'string',
createdAt: 'string',
creatorId: 'uint',
creatorName: 'string',
description: 'string',
isPrivate: 'boolean',
isPublished: 'boolean',
publishEndDate: 'string',
publishStartDate: 'string',
render: 'string',
title: 'string',
updatedAt: 'string'
})
}
static async createPage(opts) {
const page = await WIKI.models.pages.query().insertAndFetch({
await WIKI.models.pages.query().insert({
authorId: opts.authorId,
content: opts.content,
creatorId: opts.authorId,
contentType: _.get(_.find(WIKI.data.editors, ['key', opts.editor]), `contentType`, 'text'),
description: opts.description,
editorKey: opts.editor,
hash: pageHelper.generateHash({ path: opts.path, locale: opts.locale, privateNS: opts.isPrivate ? 'TODO' : '' }),
isPrivate: opts.isPrivate,
isPublished: opts.isPublished,
localeCode: opts.locale,
@@ -126,6 +129,7 @@ module.exports = class Page extends Model {
publishStartDate: opts.publishStartDate,
title: opts.title
})
const page = await WIKI.models.pages.getPageFromDb(opts)
await WIKI.models.pages.renderPage(page)
await WIKI.models.storage.pageEvent({
event: 'created',
@@ -140,7 +144,7 @@ module.exports = class Page extends Model {
throw new Error('Invalid Page Id')
}
await WIKI.models.pageHistory.addVersion(ogPage)
const page = await WIKI.models.pages.query().patchAndFetchById(ogPage.id, {
await WIKI.models.pages.query().patch({
authorId: opts.authorId,
content: opts.content,
description: opts.description,
@@ -148,7 +152,8 @@ module.exports = class Page extends Model {
publishEndDate: opts.publishEndDate,
publishStartDate: opts.publishStartDate,
title: opts.title
})
}).where('id', ogPage.id)
const page = await WIKI.models.pages.getPageFromDb(opts)
await WIKI.models.pages.renderPage(page)
await WIKI.models.storage.pageEvent({
event: 'updated',
@@ -167,4 +172,88 @@ module.exports = class Page extends Model {
removeOnFail: true
})
}
static async getPage(opts) {
let page = await WIKI.models.pages.getPageFromCache(opts)
if (!page) {
page = await WIKI.models.pages.getPageFromDb(opts)
await WIKI.models.pages.savePageToCache(page)
}
return page
}
static async getPageFromDb(opts) {
const page = await WIKI.models.pages.query()
.column([
'pages.*',
{
authorName: 'author.name',
creatorName: 'creator.name'
}
])
.joinRelation('author')
.joinRelation('creator')
.where({
'pages.path': opts.path,
'pages.localeCode': opts.locale
})
.andWhere(builder => {
builder.where({
'pages.isPublished': true
}).orWhere({
'pages.isPublished': false,
'pages.authorId': opts.userId
})
})
.andWhere(builder => {
if (opts.isPrivate) {
builder.where({ 'pages.isPrivate': true, 'pages.privateNS': opts.privateNS })
} else {
builder.where({ 'pages.isPrivate': false })
}
})
.first()
return page
}
static async savePageToCache(page) {
const cachePath = path.join(process.cwd(), `data/cache/${page.hash}.bin`)
await fs.outputFile(cachePath, WIKI.models.pages.cacheSchema.encode({
authorId: page.authorId,
authorName: page.authorName,
createdAt: page.createdAt,
creatorId: page.creatorId,
creatorName: page.creatorName,
description: page.description,
isPrivate: page.isPrivate === 1,
isPublished: page.isPublished === 1,
publishEndDate: page.publishEndDate,
publishStartDate: page.publishStartDate,
render: page.render,
title: page.title,
updatedAt: page.updatedAt
}))
}
static async getPageFromCache(opts) {
const pageHash = pageHelper.generateHash({ path: opts.path, locale: opts.locale, privateNS: opts.isPrivate ? 'TODO' : '' })
const cachePath = path.join(process.cwd(), `data/cache/${pageHash}.bin`)
try {
const pageBuffer = await fs.readFile(cachePath)
let page = WIKI.models.pages.cacheSchema.decode(pageBuffer)
return {
...page,
path: opts.path,
localeCode: opts.locale,
isPrivate: opts.isPrivate
}
} catch (err) {
if (err.code === 'ENOENT') {
return false
}
WIKI.logger.error(err)
throw err
}
}
}