From fb9a6495600ffe5babd7d89a0da22e3f8127fab7 Mon Sep 17 00:00:00 2001 From: roggervalf Date: Mon, 5 Feb 2024 18:30:20 -0500 Subject: [PATCH 01/12] test: add shared redis instances in examples --- example/bull.js | 31 +++++++++++++++++++++++++++++-- example/bullmq.js | 8 ++++---- src/server/queue/index.js | 3 --- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/example/bull.js b/example/bull.js index 0a630614..91b2059c 100644 --- a/example/bull.js +++ b/example/bull.js @@ -1,4 +1,5 @@ const express = require('express'); +const IORedis = require('ioredis'); const path = require('path'); const Arena = require('../'); const Bull = require('bull'); @@ -8,7 +9,19 @@ const HTTP_SERVER_PORT = 4735; const REDIS_SERVER_PORT = 6379; async function main() { - const queue = new Bull('name_of_my_queue', { + const queueName1 = 'name_of_my_queue_1'; + const connection = new IORedis({port: REDIS_SERVER_PORT}); + + const createClient = (type) => { + switch (type) { + case 'client': + return connection; + default: + return new IORedis({port: REDIS_SERVER_PORT}); + } + }; + + const queue = new Bull(queueName1, { redis: { port: REDIS_SERVER_PORT, }, @@ -42,7 +55,7 @@ async function main() { queues: [ { // Required for each queue definition. - name: 'name_of_my_queue', + name: queueName1, // User-readable display name for the host. Required. hostId: 'Queue Server 1', @@ -55,6 +68,20 @@ async function main() { port: REDIS_SERVER_PORT, }, }, + { + // Required for each queue definition. + name: 'name_of_my_queue_2', + + // User-readable display name for the host. Required. + hostId: 'Queue Server 2', + + // Queue type (Bull or Bee - default Bull). + type: 'bull', + + redis: { + createClient, + }, + }, ], customJsPath: 'http://localhost:4735/example.js', }, diff --git a/example/bullmq.js b/example/bullmq.js index 3fe490bf..8b358b5b 100644 --- a/example/bullmq.js +++ b/example/bullmq.js @@ -1,4 +1,5 @@ const Arena = require('../'); +const IORedis = require('ioredis'); const {Queue, Worker, FlowProducer} = require('bullmq'); // Select ports that are unlikely to be used by other services a developer might be running locally. @@ -9,6 +10,8 @@ async function main() { const queueName = 'name_of_my_queue'; const parentQueueName = 'name_of_my_parent_queue'; + const connection = new IORedis({port: REDIS_SERVER_PORT}); + const queue = new Queue(queueName, { connection: {port: REDIS_SERVER_PORT}, }); @@ -87,10 +90,7 @@ async function main() { // Queue type (Bull or Bullmq or Bee - default Bull). type: 'bullmq', - redis: { - // host: 'localhost', - port: REDIS_SERVER_PORT, - }, + redis: connection, }, { // Required for each queue definition. diff --git a/src/server/queue/index.js b/src/server/queue/index.js index feb7c6e4..34b75cf2 100644 --- a/src/server/queue/index.js +++ b/src/server/queue/index.js @@ -106,9 +106,6 @@ class Queues { queue = new Bee(name, options); queue.IS_BEE = true; } else if (isBullMQ) { - if (queueConfig.createClient) - options.createClient = queueConfig.createClient; - const {BullMQ} = this._config; const {redis, ...rest} = options; queue = new BullMQ(name, { From a107ad9b16fb8b5c20abece0ed36ca3855895e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Yepes?= <23552631+ivnnv@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:41:10 -0500 Subject: [PATCH 02/12] fix(layouts): include favicon at layout template (#668) --- src/server/views/layout.hbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/views/layout.hbs b/src/server/views/layout.hbs index b14cfabf..e71654eb 100644 --- a/src/server/views/layout.hbs +++ b/src/server/views/layout.hbs @@ -22,6 +22,8 @@ {{/if}} + + From b8fa184a6a45f91465fe5b83900a4a1253c74e87 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 8 Feb 2024 05:42:02 +0000 Subject: [PATCH 03/12] chore(release): 4.1.1 [skip ci] ### [4.1.1](https://github.com/bee-queue/arena/compare/v4.1.0...v4.1.1) (2024-02-08) ### Bug Fixes * **layouts:** include favicon at layout template ([#668](https://github.com/bee-queue/arena/issues/668)) ([a107ad9](https://github.com/bee-queue/arena/commit/a107ad9b16fb8b5c20abece0ed36ca3855895e41)) --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 838ef5d7..66380543 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### [4.1.1](https://github.com/bee-queue/arena/compare/v4.1.0...v4.1.1) (2024-02-08) + +### Bug Fixes + +- **layouts:** include favicon at layout template ([#668](https://github.com/bee-queue/arena/issues/668)) ([a107ad9](https://github.com/bee-queue/arena/commit/a107ad9b16fb8b5c20abece0ed36ca3855895e41)) + ## [4.1.0](https://github.com/bee-queue/arena/compare/v4.0.1...v4.1.0) (2023-10-28) ### Features diff --git a/package-lock.json b/package-lock.json index f1b6a3f9..954ccc83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bull-arena", - "version": "4.1.0", + "version": "4.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bull-arena", - "version": "4.1.0", + "version": "4.1.1", "license": "MIT", "dependencies": { "body-parser": "^1.20.0", diff --git a/package.json b/package.json index 9f8dbab1..750a7a97 100644 --- a/package.json +++ b/package.json @@ -66,5 +66,5 @@ "bullmq" ], "repository": "https://github.com/bee-queue/arena.git", - "version": "4.1.0" + "version": "4.1.1" } From 9ddc673dd47164e85597d1e67cd50b581c6908b1 Mon Sep 17 00:00:00 2001 From: roggervalf Date: Thu, 8 Feb 2024 21:49:33 -0500 Subject: [PATCH 04/12] chore(bull): fix createClient example --- example/bull.js | 5 +---- example/package.json | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/example/bull.js b/example/bull.js index 91b2059c..a4146e22 100644 --- a/example/bull.js +++ b/example/bull.js @@ -63,10 +63,7 @@ async function main() { // Queue type (Bull or Bee - default Bull). type: 'bull', - redis: { - // host: 'localhost', - port: REDIS_SERVER_PORT, - }, + createClient, }, { // Required for each queue definition. diff --git a/example/package.json b/example/package.json index d86490d0..7830fc62 100644 --- a/example/package.json +++ b/example/package.json @@ -19,7 +19,7 @@ "dependencies": { "@fastify/express": "^2.3.0", "bee-queue": "^1.4.0", - "bull": "^3.22.6", + "bull": "^4.12.2", "bullmq": "^4.8.0", "express": "^4.17.1", "fastify": "^4.13.0" From 3f4c6400b090b64fbcec87df03442bb8c2672790 Mon Sep 17 00:00:00 2001 From: Rogger Valverde Date: Sun, 11 Feb 2024 20:46:20 -0500 Subject: [PATCH 05/12] feat(add-job): provide editor for adding options (#670) --- public/dashboard.js | 6 ++-- src/server/queue/index.js | 4 ++- src/server/views/api/jobAdd.js | 4 +-- src/server/views/dashboard/queueDetails.js | 1 + .../dashboard/templates/queueDetails.hbs | 31 +++++++++++++++++-- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/public/dashboard.js b/public/dashboard.js index da589ab2..6375c9f2 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -256,8 +256,9 @@ $(document).ready(() => { const job = localStorage.getItem('arena:savedJob'); if (job) { - const {name, data} = JSON.parse(job); + const {name, data, opts} = JSON.parse(job); window.jsonEditor.set(data); + if (window.jsonEditorOpts) window.jsonEditorOpts.set(opts); $('input.js-add-job-name').val(name); } else { window.jsonEditor.set({id: ''}); @@ -291,7 +292,8 @@ $(document).ready(() => { $('.js-add-job').on('click', function () { const name = $('input.js-add-job-name').val() || null; const data = window.jsonEditor.get(); - const job = JSON.stringify({name, data}); + const opts = window.jsonEditorOpts ? window.jsonEditorOpts.get() : {}; + const job = JSON.stringify({name, data, opts}); localStorage.setItem('arena:savedJob', job); const {queueHost, queueName} = window.arenaInitialPayload; $.ajax({ diff --git a/src/server/queue/index.js b/src/server/queue/index.js index 34b75cf2..ff3cdb53 100644 --- a/src/server/queue/index.js +++ b/src/server/queue/index.js @@ -140,14 +140,16 @@ class Queues { * @param {Object} queue A bee or bull queue class * @param {Object} data The data to be used within the job * @param {String} name The name of the Bull job (optional) + * @param {Object} opts The opts to be used within the job */ - async set(queue, data, name) { + async set(queue, data, name, opts) { if (queue.IS_BEE) { return queue.createJob(data).save(); } else { const args = [ data, { + ...opts, removeOnComplete: false, removeOnFail: false, }, diff --git a/src/server/views/api/jobAdd.js b/src/server/views/api/jobAdd.js index 38d68669..fdd54963 100644 --- a/src/server/views/api/jobAdd.js +++ b/src/server/views/api/jobAdd.js @@ -1,6 +1,6 @@ async function handler(req, res) { const {queueName, queueHost} = req.params; - const {name, data} = req.body; + const {name, data, opts} = req.body; const {Queues} = req.app.locals; @@ -8,7 +8,7 @@ async function handler(req, res) { if (!queue) return res.status(404).json({error: 'queue not found'}); try { - await Queues.set(queue, data, name); + await Queues.set(queue, data, name, opts); } catch (err) { return res.status(500).json({error: err.message}); } diff --git a/src/server/views/dashboard/queueDetails.js b/src/server/views/dashboard/queueDetails.js index 079eb4ad..5eb577e9 100644 --- a/src/server/views/dashboard/queueDetails.js +++ b/src/server/views/dashboard/queueDetails.js @@ -35,6 +35,7 @@ async function handler(req, res) { queueName, queueHost, queueIsBee: !!queue.IS_BEE, + queueIsBullMQ: !!queue.IS_BULLMQ, hasFlows: Flows.hasFlows(), jobCounts, stats, diff --git a/src/server/views/dashboard/templates/queueDetails.hbs b/src/server/views/dashboard/templates/queueDetails.hbs index 8075e15e..396baadb 100644 --- a/src/server/views/dashboard/templates/queueDetails.hbs +++ b/src/server/views/dashboard/templates/queueDetails.hbs @@ -18,17 +18,41 @@
-
Add Job
+
Add Job

Job Types

-
+ {{#unless queueIsBee}} +
+ +
+
+
+ {{/unless}} +
+ {{#unless queueIsBee}} +
+
+
+
+
+
+
+ {{/unless}}
{{#unless queueIsBee}} + {{#if queueIsBullMQ}} + placeholder="Job name" + {{else}} + placeholder="Job name (optional)" + {{/if}} + > {{/unless}}
Create
@@ -75,6 +99,7 @@ {{#contentFor 'script'}} window.jsonEditor = new JSONEditor(document.getElementById('jsoneditor'), { modes: ['code','tree','text'] }); +if(document.getElementById('jsoneditoropts')) window.jsonEditorOpts = new JSONEditor(document.getElementById('jsoneditoropts'), { modes: ['code','tree','text'] }); window.arenaInitialPayload = { queueHost: "{{ queueHost }}", queueName: "{{ queueName }}" From 502afd35910d370b2ec488cd31034c34312771ec Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 12 Feb 2024 01:47:12 +0000 Subject: [PATCH 06/12] chore(release): 4.2.0 [skip ci] ## [4.2.0](https://github.com/bee-queue/arena/compare/v4.1.1...v4.2.0) (2024-02-12) ### Features * **add-job:** provide editor for adding options ([#670](https://github.com/bee-queue/arena/issues/670)) ([3f4c640](https://github.com/bee-queue/arena/commit/3f4c6400b090b64fbcec87df03442bb8c2672790)) --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66380543..6b81f517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.2.0](https://github.com/bee-queue/arena/compare/v4.1.1...v4.2.0) (2024-02-12) + +### Features + +- **add-job:** provide editor for adding options ([#670](https://github.com/bee-queue/arena/issues/670)) ([3f4c640](https://github.com/bee-queue/arena/commit/3f4c6400b090b64fbcec87df03442bb8c2672790)) + ### [4.1.1](https://github.com/bee-queue/arena/compare/v4.1.0...v4.1.1) (2024-02-08) ### Bug Fixes diff --git a/package-lock.json b/package-lock.json index 954ccc83..e2c2c2e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bull-arena", - "version": "4.1.1", + "version": "4.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bull-arena", - "version": "4.1.1", + "version": "4.2.0", "license": "MIT", "dependencies": { "body-parser": "^1.20.0", diff --git a/package.json b/package.json index 750a7a97..9bc5c382 100644 --- a/package.json +++ b/package.json @@ -66,5 +66,5 @@ "bullmq" ], "repository": "https://github.com/bee-queue/arena.git", - "version": "4.1.1" + "version": "4.2.0" } From 24ab67f637da2ae8add30231340e413342de8461 Mon Sep 17 00:00:00 2001 From: Rogger Valverde Date: Sat, 27 Apr 2024 12:53:29 -0600 Subject: [PATCH 07/12] feat(details): update job data (#674) --- docker-compose.yml | 7 ++++ example/bee.js | 2 +- example/bull.js | 2 +- package.json | 2 ++ public/dashboard.js | 32 ++++++++++++++++++ src/server/views/api/index.js | 2 ++ src/server/views/api/jobDataUpdate.js | 25 ++++++++++++++ .../views/dashboard/templates/jobDetails.hbs | 9 ++++- .../views/partials/dashboard/jobDetails.hbs | 33 ++++++++++++++++++- 9 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 docker-compose.yml create mode 100644 src/server/views/api/jobDataUpdate.js diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..de1b7db6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3.2' +services: + redis: + image: redis:6-alpine + container_name: redis-6 + ports: + - 6379:6379 diff --git a/example/bee.js b/example/bee.js index 7f804726..fa62cc6d 100644 --- a/example/bee.js +++ b/example/bee.js @@ -30,7 +30,7 @@ async function main() { .delayUntil(Date.now() + 60 * 1000) .save(); - const job = await queue.createJob({}).save(); + await queue.createJob({}).save(); Arena( { diff --git a/example/bull.js b/example/bull.js index a4146e22..62acf9c2 100644 --- a/example/bull.js +++ b/example/bull.js @@ -39,7 +39,7 @@ async function main() { } }); - await queue.add({}); + await queue.add({data: 'data'}); // adding delayed jobs const delayedJob = await queue.add({}, {delay: 60 * 1000}); diff --git a/package.json b/package.json index 9bc5c382..09972819 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,8 @@ "ci": "npm run lint && if [ -z \"$CI\" ]; then npm run ci:commitlint; fi", "ci:commitlint": "commitlint --from \"origin/${GITHUB_BASE_REF:-master}\"", "cm": "git cz", + "dc:up": "docker-compose -f docker-compose.yml up -d", + "dc:down": "docker-compose -f docker-compose.yml down", "dry:run": "npm publish --dry-run", "lint": "prettier -c .", "lint:staged": "lint-staged", diff --git a/public/dashboard.js b/public/dashboard.js index 6375c9f2..268abb5c 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -314,6 +314,38 @@ $(document).ready(() => { }); }); + $('.js-update-job-data').on('click', function (e) { + e.preventDefault(); + const jobId = $(this).data('job-id'); + const queueName = $(this).data('queue-name'); + const queueHost = $(this).data('queue-host'); + const stringifiedData = JSON.stringify(window.jsonEditor.get()); + const r = window.confirm( + `Update job #${jobId} data in queue "${queueHost}/${queueName}"?` + ); + + if (r) { + $.ajax({ + url: `${basePath}/api/queue/${encodeURIComponent( + queueHost + )}/${encodeURIComponent(queueName)}/job/${encodeURIComponent( + jobId + )}/data`, + type: 'PUT', + data: stringifiedData, + contentType: 'application/json', + }) + .done(() => { + alert('Job data successfully updated!'); + window.location.reload(); + }) + .fail((jqXHR) => { + window.alert('Failed to update job data, check console for error.'); + console.error(jqXHR.responseText); + }); + } + }); + $('.js-add-flow').on('click', function () { const data = window.jsonEditor.get(); const flow = JSON.stringify({data}); diff --git a/src/server/views/api/index.js b/src/server/views/api/index.js index 50523e44..12b53987 100644 --- a/src/server/views/api/index.js +++ b/src/server/views/api/index.js @@ -6,6 +6,7 @@ const jobAdd = require('./jobAdd'); const jobPromote = require('./jobPromote'); const jobRetry = require('./jobRetry'); const jobRemove = require('./jobRemove'); +const jobDataUpdate = require('./jobDataUpdate'); const repeatableJobRemove = require('./repeatableJobRemove'); const bulkJobsPromote = require('./bulkJobsPromote'); const bulkJobsRemove = require('./bulkJobsRemove'); @@ -24,6 +25,7 @@ router.delete( '/queue/:queueHost/:queueName/repeatable/job/:id', repeatableJobRemove ); +router.put('/queue/:queueHost/:queueName/job/:id/data', jobDataUpdate); router.patch('/queue/:queueHost/:queueName/job/:id', jobRetry); router.put('/queue/:queueHost/:queueName/pause', queuePause); router.put('/queue/:queueHost/:queueName/resume', queueResume); diff --git a/src/server/views/api/jobDataUpdate.js b/src/server/views/api/jobDataUpdate.js new file mode 100644 index 00000000..e9cdb5ea --- /dev/null +++ b/src/server/views/api/jobDataUpdate.js @@ -0,0 +1,25 @@ +async function handler(req, res) { + const {queueName, queueHost, id} = req.params; + const data = req.body; + + const {Queues} = req.app.locals; + + const queue = await Queues.get(queueName, queueHost); + if (!queue) return res.status(404).json({error: 'queue not found'}); + + const job = await queue.getJob(id); + if (!job) return res.status(404).send({error: 'job not found'}); + + try { + if (job.updateData) { + await job.updateData(data); + } else { + await job.update(data); + } + } catch (err) { + return res.status(500).json({error: err.message}); + } + return res.sendStatus(200); +} + +module.exports = handler; diff --git a/src/server/views/dashboard/templates/jobDetails.hbs b/src/server/views/dashboard/templates/jobDetails.hbs index 8b06853b..781a51ab 100644 --- a/src/server/views/dashboard/templates/jobDetails.hbs +++ b/src/server/views/dashboard/templates/jobDetails.hbs @@ -1,6 +1,6 @@

Queue {{ queueHost }}/{{ queueName }}

-{{> dashboard/jobDetails job basePath=basePath queueName=queueName queueHost=queueHost jobState=jobState stacktraces=stacktraces}} +{{> dashboard/jobDetails job basePath=basePath queueName=queueName queueHost=queueHost jobState=jobState stacktraces=stacktraces view=true}} {{#contentFor 'sidebar'}}
  • Queues Overview
  • @@ -12,4 +12,11 @@ {{#if hasFlows}}
  • Flows Overview
  • {{/if}} +{{/contentFor}} + +{{#contentFor 'script'}} +if(document.getElementById('jsoneditor')) { + window.jsonEditor = new JSONEditor(document.getElementById('jsoneditor'), { modes: ['code','tree','text'] }); + window.jsonEditor.set({{json job.data true}}) +} {{/contentFor}} \ No newline at end of file diff --git a/src/server/views/partials/dashboard/jobDetails.hbs b/src/server/views/partials/dashboard/jobDetails.hbs index c31f9528..ceffac50 100644 --- a/src/server/views/partials/dashboard/jobDetails.hbs +++ b/src/server/views/partials/dashboard/jobDetails.hbs @@ -75,8 +75,10 @@
    Permalinks
    + {{#unless view}} Job {{ this.id }} + {{/unless}} JSON
    @@ -133,7 +135,36 @@
    Data
    -
    {{json this.data true}}
    + +{{#unless queue.IS_BEE}} +{{#if view }} +
    + +
    +
    +
    +{{/if}} +{{/unless}} +
    {{json this.data true}}
    +{{#unless queue.IS_BEE}} +{{#if view }} +
    +
    +
    +
    +
    +
    Update
    +
    +
    +
    +
    +
    +{{/if}} +{{/unless}} {{#if this.queue.IS_BULLMQ}} {{#if this.parent }} From 956c5f6dce12d92620eb63a48bac83b85ed79448 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 27 Apr 2024 18:54:20 +0000 Subject: [PATCH 08/12] chore(release): 4.3.0 [skip ci] ## [4.3.0](https://github.com/bee-queue/arena/compare/v4.2.0...v4.3.0) (2024-04-27) ### Features * **details:** update job data ([#674](https://github.com/bee-queue/arena/issues/674)) ([24ab67f](https://github.com/bee-queue/arena/commit/24ab67f637da2ae8add30231340e413342de8461)) --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b81f517..a76ed8d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.3.0](https://github.com/bee-queue/arena/compare/v4.2.0...v4.3.0) (2024-04-27) + +### Features + +- **details:** update job data ([#674](https://github.com/bee-queue/arena/issues/674)) ([24ab67f](https://github.com/bee-queue/arena/commit/24ab67f637da2ae8add30231340e413342de8461)) + ## [4.2.0](https://github.com/bee-queue/arena/compare/v4.1.1...v4.2.0) (2024-02-12) ### Features diff --git a/package-lock.json b/package-lock.json index e2c2c2e2..d40d6b62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bull-arena", - "version": "4.2.0", + "version": "4.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bull-arena", - "version": "4.2.0", + "version": "4.3.0", "license": "MIT", "dependencies": { "body-parser": "^1.20.0", diff --git a/package.json b/package.json index 09972819..cb158e62 100644 --- a/package.json +++ b/package.json @@ -68,5 +68,5 @@ "bullmq" ], "repository": "https://github.com/bee-queue/arena.git", - "version": "4.2.0" + "version": "4.3.0" } From e62aef022cf771b715cf65d100391f6f88c5cfd5 Mon Sep 17 00:00:00 2001 From: Rogger Valverde Date: Thu, 2 May 2024 23:41:59 -0600 Subject: [PATCH 09/12] feat(bull): add clean jobs button for completed and failed (#675) --- public/dashboard.js | 72 ++++++++++++------- src/server/views/api/bulkAction.js | 7 +- src/server/views/api/bulkJobsClean.js | 3 + src/server/views/api/index.js | 2 + .../views/dashboard/queueJobsByState.js | 6 ++ .../dashboard/templates/queueJobsByState.hbs | 6 ++ 6 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 src/server/views/api/bulkJobsClean.js diff --git a/public/dashboard.js b/public/dashboard.js index 268abb5c..eecb4244 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -210,38 +210,60 @@ $(document).ready(() => { queueState, }; - $bulkActionContainer.each((index, value) => { - const isChecked = $(value).find('[name=jobChecked]').is(':checked'); - const id = encodeURIComponent($(value).find('[name=jobId]').val()); + if (action !== 'clean') { + $bulkActionContainer.each((index, value) => { + const isChecked = $(value).find('[name=jobChecked]').is(':checked'); + const id = encodeURIComponent($(value).find('[name=jobId]').val()); + + if (isChecked) { + data.jobs.push(id); + } + }); + } - if (isChecked) { - data.jobs.push(id); - } - }); + const count = action === 'clean' ? 1000 : data.jobs.length; const r = window.confirm( - `${capitalize(action)} ${data.jobs.length} ${ - data.jobs.length > 1 ? 'jobs' : 'job' + `${capitalize(action)} ${count} ${ + count > 1 ? 'jobs' : 'job' } in queue "${queueHost}/${queueName}"?` ); if (r) { - $.ajax({ - method: action === 'remove' ? 'POST' : 'PATCH', - url: `${basePath}/api/queue/${encodeURIComponent( - queueHost - )}/${encodeURIComponent(queueName)}/${ - action === 'promote' ? 'delayed/' : '' - }job/bulk`, - data: JSON.stringify(data), - contentType: 'application/json', - }) - .done(() => { - window.location.reload(); + if (action === 'clean') { + $.ajax({ + method: 'DELETE', + url: `${basePath}/api/queue/${encodeURIComponent( + queueHost + )}/${encodeURIComponent(queueName)}/jobs/bulk`, + data: JSON.stringify(data), + contentType: 'application/json', }) - .fail((jqXHR) => { - window.alert(`Request failed, check console for error.`); - console.error(jqXHR.responseText); - }); + .done(() => { + window.location.reload(); + }) + .fail((jqXHR) => { + window.alert(`Request failed, check console for error.`); + console.error(jqXHR.responseText); + }); + } else { + $.ajax({ + method: action === 'remove' ? 'POST' : 'PATCH', + url: `${basePath}/api/queue/${encodeURIComponent( + queueHost + )}/${encodeURIComponent(queueName)}/${ + action === 'promote' ? 'delayed/' : '' + }job/bulk`, + data: JSON.stringify(data), + contentType: 'application/json', + }) + .done(() => { + window.location.reload(); + }) + .fail((jqXHR) => { + window.alert(`Request failed, check console for error.`); + console.error(jqXHR.responseText); + }); + } } else { $(this).prop('disabled', false); } diff --git a/src/server/views/api/bulkAction.js b/src/server/views/api/bulkAction.js index ae8ae206..3b42153c 100644 --- a/src/server/views/api/bulkAction.js +++ b/src/server/views/api/bulkAction.js @@ -1,6 +1,6 @@ const _ = require('lodash'); -const ACTIONS = ['remove', 'retry', 'promote']; +const ACTIONS = ['clean', 'remove', 'retry', 'promote']; function bulkAction(action) { return async function handler(req, res) { @@ -19,7 +19,7 @@ function bulkAction(action) { const {jobs, queueState} = req.body; try { - if (!_.isEmpty(jobs)) { + if (!_.isEmpty(jobs) && job.length > 0) { const jobsPromises = jobs.map((id) => queue.getJob(decodeURIComponent(id)) ); @@ -39,6 +39,9 @@ function bulkAction(action) { : fetchedJobs.map((job) => job[action]()); await Promise.all(actionPromises); return res.sendStatus(200); + } else if (action === 'clean') { + await queue.clean(1000, queueState); + return res.sendStatus(200); } } catch (e) { const body = { diff --git a/src/server/views/api/bulkJobsClean.js b/src/server/views/api/bulkJobsClean.js new file mode 100644 index 00000000..92c5241a --- /dev/null +++ b/src/server/views/api/bulkJobsClean.js @@ -0,0 +1,3 @@ +const bulkAction = require('./bulkAction'); + +module.exports = bulkAction('clean'); diff --git a/src/server/views/api/index.js b/src/server/views/api/index.js index 12b53987..ef4b6350 100644 --- a/src/server/views/api/index.js +++ b/src/server/views/api/index.js @@ -8,6 +8,7 @@ const jobRetry = require('./jobRetry'); const jobRemove = require('./jobRemove'); const jobDataUpdate = require('./jobDataUpdate'); const repeatableJobRemove = require('./repeatableJobRemove'); +const bulkJobsClean = require('./bulkJobsClean'); const bulkJobsPromote = require('./bulkJobsPromote'); const bulkJobsRemove = require('./bulkJobsRemove'); const bulkJobsRetry = require('./bulkJobsRetry'); @@ -30,5 +31,6 @@ router.patch('/queue/:queueHost/:queueName/job/:id', jobRetry); router.put('/queue/:queueHost/:queueName/pause', queuePause); router.put('/queue/:queueHost/:queueName/resume', queueResume); router.delete('/queue/:queueHost/:queueName/job/:id', jobRemove); +router.delete('/queue/:queueHost/:queueName/jobs/bulk', bulkJobsClean); module.exports = router; diff --git a/src/server/views/dashboard/queueJobsByState.js b/src/server/views/dashboard/queueJobsByState.js index c9272724..8b25ea49 100644 --- a/src/server/views/dashboard/queueJobsByState.js +++ b/src/server/views/dashboard/queueJobsByState.js @@ -153,6 +153,11 @@ async function _html(req, res) { state === 'failed' || (state === 'delayed' && !queue.IS_BEE) ); + const disableClean = !( + state === 'failed' || + state === 'completed' || + !queue.IS_BULL + ); return res.render('dashboard/templates/queueJobsByState', { basePath, @@ -164,6 +169,7 @@ async function _html(req, res) { disablePagination: queue.IS_BEE && (state === 'succeeded' || state === 'failed'), disableOrdering: queue.IS_BEE, + disableClean, disablePromote, disableRetry, currentPage: page, diff --git a/src/server/views/dashboard/templates/queueJobsByState.hbs b/src/server/views/dashboard/templates/queueJobsByState.hbs index ca7a757a..d41dfa8d 100644 --- a/src/server/views/dashboard/templates/queueJobsByState.hbs +++ b/src/server/views/dashboard/templates/queueJobsByState.hbs @@ -50,6 +50,12 @@ data-queue-state="{{ state }}" class="js-bulk-action btn btn-danger"> Remove Jobs + {{#unless disableClean}} + + {{/unless}} {{#unless disableRetry}}