storage.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. const Model = require('objection').Model
  2. const path = require('path')
  3. const fs = require('fs-extra')
  4. const _ = require('lodash')
  5. const yaml = require('js-yaml')
  6. const commonHelper = require('../helpers/common')
  7. /**
  8. * Storage model
  9. */
  10. module.exports = class Storage extends Model {
  11. static get tableName() { return 'storage' }
  12. static get idColumn() { return 'id' }
  13. static get jsonSchema () {
  14. return {
  15. type: 'object',
  16. required: ['module', 'isEnabled', 'siteId'],
  17. properties: {
  18. module: {type: 'string'},
  19. isEnabled: {type: 'boolean'}
  20. }
  21. }
  22. }
  23. static get jsonAttributes() {
  24. return ['contentTypes', 'assetDelivery', 'versioning', 'schedule', 'config', 'state']
  25. }
  26. static async getTargets ({ siteId }) {
  27. return WIKI.db.storage.query().where(builder => {
  28. if (siteId) {
  29. builder.where('siteId', siteId)
  30. }
  31. })
  32. }
  33. static async refreshTargetsFromDisk () {
  34. let trx
  35. try {
  36. // -> Fetch definitions from disk
  37. const storageDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/storage'))
  38. WIKI.storage.defs = []
  39. for (const dir of storageDirs) {
  40. const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/storage', dir, 'definition.yml'), 'utf8')
  41. const defParsed = yaml.load(def)
  42. defParsed.key = dir
  43. defParsed.isLoaded = false
  44. WIKI.storage.defs.push(defParsed)
  45. WIKI.logger.debug(`Loaded storage module definition ${dir}: [ OK ]`)
  46. }
  47. WIKI.logger.info(`Loaded ${WIKI.storage.defs.length} storage module definitions: [ OK ]`)
  48. } catch (err) {
  49. WIKI.logger.error('Failed to scan or load new storage providers: [ FAILED ]')
  50. WIKI.logger.error(err)
  51. if (trx) {
  52. trx.rollback()
  53. }
  54. }
  55. }
  56. /**
  57. * Ensure a storage module is loaded
  58. */
  59. static async ensureModule (moduleName) {
  60. if (!_.has(WIKI.storage.modules, moduleName)) {
  61. try {
  62. WIKI.storage.modules[moduleName] = require(`../modules/storage/${moduleName}/storage`)
  63. WIKI.logger.debug(`Activated storage module ${moduleName}: [ OK ]`)
  64. return true
  65. } catch (err) {
  66. WIKI.logger.warn(`Failed to load storage module ${moduleName}: [ FAILED ]`)
  67. WIKI.logger.warn(err)
  68. return false
  69. }
  70. } else {
  71. return true
  72. }
  73. }
  74. /**
  75. * Initialize active storage targets
  76. */
  77. static async initTargets () {
  78. const dbTargets = await WIKI.db.storage.query().where('isEnabled', true)
  79. const activeModules = _.uniq(dbTargets.map(t => t.module))
  80. try {
  81. // -> Stop and delete existing jobs
  82. // const prevjobs = _.remove(WIKI.scheduler.jobs, job => job.name === 'sync-storage')
  83. // if (prevjobs.length > 0) {
  84. // prevjobs.forEach(job => job.stop())
  85. // }
  86. // -> Load active modules
  87. for (const md of activeModules) {
  88. this.ensureModule(md)
  89. }
  90. // -> Initialize targets
  91. // for (const target of this.targets) {
  92. // const targetDef = _.find(WIKI.data.storage, ['key', target.key])
  93. // target.fn = require(`../modules/storage/${target.key}/storage`)
  94. // target.fn.config = target.config
  95. // target.fn.mode = target.mode
  96. // try {
  97. // await target.fn.init()
  98. // // -> Save succeeded init state
  99. // await WIKI.db.storage.query().patch({
  100. // state: {
  101. // status: 'operational',
  102. // message: '',
  103. // lastAttempt: new Date().toISOString()
  104. // }
  105. // }).where('key', target.key)
  106. // // -> Set recurring sync job
  107. // if (targetDef.schedule && target.syncInterval !== 'P0D') {
  108. // WIKI.scheduler.registerJob({
  109. // name: 'sync-storage',
  110. // immediate: false,
  111. // schedule: target.syncInterval,
  112. // repeat: true
  113. // }, target.key)
  114. // }
  115. // // -> Set internal recurring sync job
  116. // if (targetDef.internalSchedule && targetDef.internalSchedule !== 'P0D') {
  117. // WIKI.scheduler.registerJob({
  118. // name: 'sync-storage',
  119. // immediate: false,
  120. // schedule: target.internalSchedule,
  121. // repeat: true
  122. // }, target.key)
  123. // }
  124. // } catch (err) {
  125. // // -> Save initialization error
  126. // await WIKI.db.storage.query().patch({
  127. // state: {
  128. // status: 'error',
  129. // message: err.message,
  130. // lastAttempt: new Date().toISOString()
  131. // }
  132. // }).where('key', target.key)
  133. // }
  134. // }
  135. } catch (err) {
  136. WIKI.logger.warn(err)
  137. throw err
  138. }
  139. }
  140. static async pageEvent({ event, page }) {
  141. try {
  142. for (let target of this.targets) {
  143. await target.fn[event](page)
  144. }
  145. } catch (err) {
  146. WIKI.logger.warn(err)
  147. throw err
  148. }
  149. }
  150. static async assetEvent({ event, asset }) {
  151. try {
  152. for (let target of this.targets) {
  153. await target.fn[`asset${_.capitalize(event)}`](asset)
  154. }
  155. } catch (err) {
  156. WIKI.logger.warn(err)
  157. throw err
  158. }
  159. }
  160. static async getLocalLocations({ asset }) {
  161. const locations = []
  162. const promises = this.targets.map(async (target) => {
  163. try {
  164. const path = await target.fn.getLocalLocation(asset)
  165. locations.push({
  166. path,
  167. key: target.key
  168. })
  169. } catch (err) {
  170. WIKI.logger.warn(err)
  171. }
  172. })
  173. await Promise.all(promises)
  174. return locations
  175. }
  176. static async executeAction(targetKey, handler) {
  177. try {
  178. const target = _.find(this.targets, ['key', targetKey])
  179. if (target) {
  180. if (_.hasIn(target.fn, handler)) {
  181. await target.fn[handler]()
  182. } else {
  183. throw new Error('Invalid Handler for Storage Target')
  184. }
  185. } else {
  186. throw new Error('Invalid or Inactive Storage Target')
  187. }
  188. } catch (err) {
  189. WIKI.logger.warn(err)
  190. throw err
  191. }
  192. }
  193. }