diff --git a/server/index.js b/server/index.js index 13377b79..949fbeaf 100644 --- a/server/index.js +++ b/server/index.js @@ -22,12 +22,36 @@ const contentApiPreparePathService = require('./content-api/services/prepare-pat const contentApiByPathService = require('./content-api/services/by-path'); const contentApiPathRoutes = require('./content-api/routes/path'); +// Queue API +const queueApiQueueSchema = require('./queue/content-types/queue/schema.json'); +const queueApiJobSchema = require('./queue/content-types/job/schema.json'); +const queueApiQueueService = require('./queue/services/queue'); +const queueApiQueueHelperService = require('./queue/services/helpers'); +// const { getPluginService } = require('./util/getPluginService'); + module.exports = { register: async ({ strapi }) => { await adminApiRegister(strapi); }, bootstrap: async () => { await adminApiBootstrap(); + + // const queueName = 'url-alias creation queue 9'; + // await getPluginService('queueService').process(queueName, async (job, done) => { + // console.log('we be processing the job breh', job.data); + // done(); + // }); + + // await getPluginService('queueService').create(queueName); + // await getPluginService('queueService').addJob(queueName, { + // some: 'data', + // }); + // await getPluginService('queueService').addJob(queueName, { + // some: 'more data', + // }); + // await getPluginService('queueService').addJob(queueName, { + // some: 'even data', + // }); }, contentTypes: { path: { @@ -36,6 +60,12 @@ module.exports = { pattern: { schema: adminApiPatternSchema, }, + queue: { + schema: queueApiQueueSchema, + }, + job: { + schema: queueApiJobSchema, + }, }, routes: { admin: { @@ -66,5 +96,7 @@ module.exports = { lifecycleService: adminApiLifecycleService, byPathService: contentApiByPathService, overrideQueryLayer: adminApiOverrideQueryLayerService, + queueService: queueApiQueueService, + queueHelpers: queueApiQueueHelperService, }, }; diff --git a/server/queue/bootstrap.js b/server/queue/bootstrap.js new file mode 100644 index 00000000..f44ba4bd --- /dev/null +++ b/server/queue/bootstrap.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = async () => { + +}; diff --git a/server/queue/content-types/job/schema.json b/server/queue/content-types/job/schema.json new file mode 100644 index 00000000..77432503 --- /dev/null +++ b/server/queue/content-types/job/schema.json @@ -0,0 +1,34 @@ +{ + "kind": "collectionType", + "collectionName": "queue_job", + "info": { + "singularName": "job", + "pluralName": "jobs", + "displayName": "job", + "description": "" + }, + "options": { + "draftAndPublish": false, + "comment": "" + }, + "pluginOptions": { + "content-manager": { + "visible": true + }, + "content-type-builder": { + "visible": true + } + }, + "attributes": { + "queue": { + "type": "relation", + "relation": "manyToOne", + "target": "plugin::url-alias.queue", + "inversedBy": "queue_jobs" + }, + "data": { + "type": "json", + "required": true + } + } +} diff --git a/server/queue/content-types/queue/schema.json b/server/queue/content-types/queue/schema.json new file mode 100644 index 00000000..bdc21c4b --- /dev/null +++ b/server/queue/content-types/queue/schema.json @@ -0,0 +1,45 @@ +{ + "kind": "collectionType", + "collectionName": "queue", + "info": { + "singularName": "queue", + "pluralName": "queues", + "displayName": "queue", + "description": "" + }, + "options": { + "draftAndPublish": false, + "comment": "" + }, + "pluginOptions": { + "content-manager": { + "visible": true + }, + "content-type-builder": { + "visible": true + } + }, + "attributes": { + "name": { + "type": "string", + "unique": true, + "required": true + }, + "progress": { + "required": true, + "min": 0, + "max": 100, + "default": 0, + "type": "integer" + }, + "paused": { + "type": "boolean" + }, + "queue_jobs": { + "type": "relation", + "relation": "oneToMany", + "target": "plugin::url-alias.job", + "mappedBy": "queue" + } + } +} diff --git a/server/queue/services/helpers.js b/server/queue/services/helpers.js new file mode 100644 index 00000000..442a885f --- /dev/null +++ b/server/queue/services/helpers.js @@ -0,0 +1,81 @@ +'use strict'; + +const { getPluginService } = require('../../util/getPluginService'); + +module.exports = () => ({ + /** + * Get a queue by it's name. + * + * @param {string} name the name. + * @returns {void} + */ + getQueue: async (name) => { + try { + const queues = await strapi.entityService.findMany('plugin::url-alias.queue', { + filters: { + name, + }, + populate: { + queue_jobs: true, + }, + }); + + return queues[0]; + } catch (e) { + strapi.log.error(e); + } + }, + + /** + * Create a job. + * + * @param {string} queueId the id of the queue. + * @param {object} data the data of the job. + * @returns {void} + */ + createJob: async (queueId, data) => { + try { + return await strapi.entityService.create('plugin::url-alias.job', { + data: { + data, + queue: queueId, + }, + }); + } catch (e) { + strapi.log.error(e); + } + }, + + /** + * Deletes a job. + * + * @param {obj} job the job to delete. + * @returns {void} + */ + deleteJob: async (job) => { + try { + await strapi.entityService.delete('plugin::url-alias.job', job.id); + } catch (e) { + strapi.log.error(e); + } + }, + + /** + * Update the progress + * + * @param {number} queueId the id of the queue to update. + * @param {number} progress the new progress. + * @returns {void} + */ + updateProgress: async (queueId, progress) => { + try { + await strapi.entityService.update('plugin::url-alias.queue', queueId, { + data: { + progress: Math.floor(progress), + }, + }); + } catch (e) { + strapi.log.error(e); + } + }, +}); diff --git a/server/queue/services/queue.js b/server/queue/services/queue.js new file mode 100644 index 00000000..f576a5ff --- /dev/null +++ b/server/queue/services/queue.js @@ -0,0 +1,66 @@ +'use strict'; + +const { getPluginService } = require('../../util/getPluginService'); + +module.exports = () => ({ + /** + * Create queue. + * + * @param {string} name the name. + * @returns {void} + */ + create: async (name) => { + try { + return await strapi.entityService.create('plugin::url-alias.queue', { + data: { + name, + }, + }); + } catch (e) { + strapi.log.error(e); + } + }, + + /** + * Add job. + * + * @param {string} name the name of the queue. + * @param {object} data the data of the job. + * @returns {void} + */ + addJob: async (name, data) => { + try { + const queue = await getPluginService('queueHelpers').getQueue(name); + await getPluginService('queueHelpers').createJob(queue.id, data); + } catch (e) { + strapi.log.error(e); + } + }, + + /** + * Process the queue. + * + * @param {string} name the name of the queue. + * @param {function} fn the process function. + * @returns {void} + */ + process: async (name, fn) => { + const queue = await getPluginService('queueHelpers').getQueue(name); + const queueSizeOnePercent = queue.queue_jobs.length / 100; + let queueSize = queue.queue_jobs.length; + + const done = async (job) => { + await getPluginService('queueHelpers').deleteJob(job); + queueSize--; + const progress = 100 - (queueSize / queueSizeOnePercent); + await getPluginService('queueHelpers').updateProgress(queue.id, progress); + }; + + queue.queue_jobs.map((job) => { + fn(job, () => done(job)); + }); + + // TODO: + // Delete the queue. + }, +});