feat: storage disk - actions + daily backup
This commit is contained in:
parent
6ea3ff11ea
commit
e2518c7a8d
@ -157,6 +157,7 @@
|
||||
"sqlite3": "4.0.6",
|
||||
"striptags": "3.1.1",
|
||||
"subscriptions-transport-ws": "0.9.15",
|
||||
"tar-fs": "2.0.0",
|
||||
"twemoji": "11.3.0",
|
||||
"uslug": "1.0.4",
|
||||
"uuid": "3.3.2",
|
||||
|
@ -142,6 +142,16 @@ module.exports = class Storage extends Model {
|
||||
repeat: true
|
||||
}, target.key)
|
||||
}
|
||||
|
||||
// -> Set internal recurring sync job
|
||||
if (targetDef.intervalSchedule && targetDef.intervalSchedule !== `P0D`) {
|
||||
WIKI.scheduler.registerJob({
|
||||
name: `sync-storage`,
|
||||
immediate: false,
|
||||
schedule: target.intervalSchedule,
|
||||
repeat: true
|
||||
}, target.key)
|
||||
}
|
||||
} catch (err) {
|
||||
// -> Save initialization error
|
||||
await WIKI.models.storage.query().patch({
|
||||
|
@ -9,6 +9,7 @@ supportedModes:
|
||||
- push
|
||||
defaultMode: push
|
||||
schedule: false
|
||||
internalSchedule: P1D
|
||||
props:
|
||||
path:
|
||||
type: String
|
||||
@ -21,3 +22,10 @@ props:
|
||||
title: Create Daily Backups
|
||||
hint: A tar.gz archive containing all content will be created daily in subfolder named _daily. Archives are kept for a month.
|
||||
order: 2
|
||||
actions:
|
||||
- handler: dump
|
||||
label: Dump all content to disk
|
||||
hint: Output all content from the DB to the local disk. If you enabled this module after content was created or you temporarily disabled this module, you'll want to execute this action to add the missing files.
|
||||
- handler: backup
|
||||
label: Create Backup
|
||||
hint: Will create a manual backup archive at this point in time, in a subfolder named _manual, from the contents currently on disk.
|
||||
|
@ -1,5 +1,15 @@
|
||||
const fs = require('fs-extra')
|
||||
const _ = require('lodash')
|
||||
const path = require('path')
|
||||
const tar = require('tar-fs')
|
||||
const zlib = require('zlib')
|
||||
const stream = require('stream')
|
||||
const Promise = require('bluebird')
|
||||
const pipeline = Promise.promisify(stream.pipeline)
|
||||
const pageHelper = require('../../../helpers/page.js')
|
||||
const moment = require('moment')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
/**
|
||||
* Get file extension based on content type
|
||||
@ -27,8 +37,25 @@ module.exports = {
|
||||
await fs.ensureDir(this.config.path)
|
||||
WIKI.logger.info('(STORAGE/DISK) Initialization completed.')
|
||||
},
|
||||
async sync() {
|
||||
// not used
|
||||
async sync({ manual } = { manual: false }) {
|
||||
if (this.config.createDailyBackups || manual) {
|
||||
const dirPath = path.join(this.config.path, manual ? '_manual' : '_daily')
|
||||
await fs.ensureDir(dirPath)
|
||||
|
||||
const dateFilename = moment().format(manual ? 'YYYYMMDD-HHmmss' : 'DD')
|
||||
|
||||
WIKI.logger.info(`(STORAGE/DISK) Creating backup archive...`)
|
||||
await pipeline(
|
||||
tar.pack(this.config.path, {
|
||||
ignore: (filePath) => {
|
||||
return filePath.indexOf('_daily') >= 0 || filePath.indexOf('_manual') >= 0
|
||||
}
|
||||
}),
|
||||
zlib.createGzip(),
|
||||
fs.createWriteStream(path.join(dirPath, `wiki-${dateFilename}.tar.gz`))
|
||||
)
|
||||
WIKI.logger.info('(STORAGE/DISK) Backup archive created successfully.')
|
||||
}
|
||||
},
|
||||
async created(page) {
|
||||
WIKI.logger.info(`(STORAGE/DISK) Creating file ${page.path}...`)
|
||||
@ -50,5 +77,31 @@ module.exports = {
|
||||
const sourceFilePath = path.join(this.config.path, `${page.sourcePath}.${getFileExtension(page.contentType)}`)
|
||||
const destinationFilePath = path.join(this.config.path, `${page.destinationPath}.${getFileExtension(page.contentType)}`)
|
||||
await fs.move(sourceFilePath, destinationFilePath, { overwrite: true })
|
||||
},
|
||||
|
||||
/**
|
||||
* HANDLERS
|
||||
*/
|
||||
async dump() {
|
||||
WIKI.logger.info(`(STORAGE/DISK) Dumping all content to disk...`)
|
||||
await pipeline(
|
||||
WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'contentType', 'content', 'isPublished', 'updatedAt').select().from('pages').where({
|
||||
isPrivate: false
|
||||
}).stream(),
|
||||
new stream.Transform({
|
||||
objectMode: true,
|
||||
transform: async (page, enc, cb) => {
|
||||
const fileName = `${page.path}.${getFileExtension(page.contentType)}`
|
||||
WIKI.logger.info(`(STORAGE/DISK) Dumping ${fileName}...`)
|
||||
const filePath = path.join(this.config.path, fileName)
|
||||
await fs.outputFile(filePath, pageHelper.injectPageMetadata(page), 'utf8')
|
||||
cb()
|
||||
}
|
||||
})
|
||||
)
|
||||
WIKI.logger.info('(STORAGE/DISK) All content was dumped to disk successfully.')
|
||||
},
|
||||
async backup() {
|
||||
return this.sync({ manual: true })
|
||||
}
|
||||
}
|
||||
|
@ -12438,6 +12438,11 @@ tapable@^1.0.0, tapable@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e"
|
||||
integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==
|
||||
|
||||
tar-js@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-js/-/tar-js-0.3.0.tgz#6949aabfb0ba18bb1562ae51a439fd0f30183a17"
|
||||
integrity sha1-aUmqv7C6GLsVYq5RpDn9DzAYOhc=
|
||||
|
||||
tar@^2.0.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
|
||||
|
Loading…
Reference in New Issue
Block a user