Skip to content

Commit ab2f6af

Browse files
authored
feat(queue): support updating queue configuration (#687)
1 parent 8a62e6c commit ab2f6af

File tree

6 files changed

+119
-3
lines changed

6 files changed

+119
-3
lines changed

example/bullmq.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ async function main() {
3737
}
3838
},
3939
{
40-
concurrency: 3,
40+
concurrency: 10,
4141
connection: {port: REDIS_SERVER_PORT},
4242
}
4343
);

public/dashboard.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,48 @@ $(document).ready(() => {
286286
}
287287
});
288288

289+
$('.js-toggle-update-queue-meta').on('click', function () {
290+
const updateMetaText = $('.js-toggle-update-queue-meta').text();
291+
const shouldNotHide = updateMetaText === 'Update';
292+
const newUpdateMetaText = shouldNotHide ? 'Cancel' : 'Update';
293+
$('.meta-config-editor').toggleClass('hide', !shouldNotHide);
294+
$('.js-toggle-update-queue-meta').text(newUpdateMetaText);
295+
});
296+
297+
$('.js-update-queue-meta').on('click', function () {
298+
const {queueHost, queueName} = window.arenaInitialPayload;
299+
const concurrency = $('input.js-update-meta-concurrency').val() || null;
300+
const max = $('input.js-update-meta-rl-max').val() || null;
301+
const duration = $('input.js-update-meta-rl-duration').val() || null;
302+
303+
const stringifiedData = JSON.stringify({
304+
concurrency: concurrency ? parseInt(concurrency, 10) : null,
305+
max: max ? parseInt(max, 10) : null,
306+
duration: duration ? parseInt(duration, 10) : null,
307+
});
308+
309+
const response = window.confirm(
310+
`Are you sure you want to update the queue "${queueHost}/${queueName}" configuration?`
311+
);
312+
if (response) {
313+
$.ajax({
314+
url: `${basePath}/api/queue/${encodeURIComponent(
315+
queueHost
316+
)}/${encodeURIComponent(queueName)}/update-meta`,
317+
type: 'PUT',
318+
data: stringifiedData,
319+
contentType: 'application/json',
320+
})
321+
.done(() => {
322+
window.location.reload();
323+
})
324+
.fail((jqXHR) => {
325+
window.alert(`Request failed, check console for error.`);
326+
console.error(jqXHR.responseText);
327+
});
328+
}
329+
});
330+
289331
$('.js-toggle-add-flow-editor').on('click', function () {
290332
const addFlowText = $('.js-toggle-add-flow-editor').text();
291333
const shouldNotHide = addFlowText === 'Add Flow';

src/server/views/api/bulkAction.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ function bulkAction(action) {
4040
await Promise.all(actionPromises);
4141
return res.sendStatus(200);
4242
} else if (action === 'clean') {
43-
await queue.clean(1000, queueState);
43+
if (queue.IS_BULLMQ) {
44+
await queue.clean(0, 1000, queueState);
45+
} else {
46+
await queue.clean(1000, queueState);
47+
}
48+
4449
return res.sendStatus(200);
4550
}
4651
} catch (e) {

src/server/views/api/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const bulkJobsRemove = require('./bulkJobsRemove');
1414
const bulkJobsRetry = require('./bulkJobsRetry');
1515
const queuePause = require('./queuePause');
1616
const queueResume = require('./queueResume');
17+
const queueUpdateMeta = require('./queueUpdateMeta');
1718

1819
router.post('/queue/:queueHost/:queueName/job', jobAdd);
1920
router.post('/flow/:flowHost/:connectionName/flow', addFlow);
@@ -30,6 +31,7 @@ router.put('/queue/:queueHost/:queueName/job/:id/data', jobDataUpdate);
3031
router.patch('/queue/:queueHost/:queueName/job/:id', jobRetry);
3132
router.put('/queue/:queueHost/:queueName/pause', queuePause);
3233
router.put('/queue/:queueHost/:queueName/resume', queueResume);
34+
router.put('/queue/:queueHost/:queueName/update-meta', queueUpdateMeta);
3335
router.delete('/queue/:queueHost/:queueName/job/:id', jobRemove);
3436
router.delete('/queue/:queueHost/:queueName/jobs/bulk', bulkJobsClean);
3537

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
async function handler(req, res) {
2+
const {queueName, queueHost} = req.params;
3+
const data = req.body;
4+
5+
const {Queues} = req.app.locals;
6+
7+
const queue = await Queues.get(queueName, queueHost);
8+
9+
if (!queue) return res.status(404).json({error: 'queue not found'});
10+
11+
try {
12+
if (queue.setGlobalConcurrency && queue.setGlobalRateLimit) {
13+
if (data.concurrency !== null && data.concurrency !== undefined) {
14+
await queue.setGlobalConcurrency(data.concurrency);
15+
} else {
16+
await queue.removeGlobalConcurrency();
17+
}
18+
19+
if (
20+
data.max !== null &&
21+
data.max !== undefined &&
22+
data.duration !== null &&
23+
data.duration !== undefined
24+
) {
25+
await queue.setGlobalRateLimit(data.max, data.duration);
26+
} else {
27+
await queue.removeGlobalRateLimit();
28+
}
29+
}
30+
} catch (err) {
31+
console.log('err', err);
32+
return res.status(500).json({error: err.message});
33+
}
34+
return res.sendStatus(200);
35+
}
36+
37+
module.exports = handler;

src/server/views/dashboard/templates/queueDetails.hbs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,40 @@
8989
{{#if globalConfig}}
9090
<div class="panel panel-default">
9191
<div class="panel-heading">
92+
<div class="js-toggle-update-queue-meta btn btn-default btn-xs pull-right">Update</div>
9293
<h4 class="panel-title">Global Configuration</h4>
9394
</div>
9495
<div class="panel-body">
95-
<table class="table">
96+
<div class="meta-config-editor panel-body hide overflow-hidden">
97+
<div class="form-group row">
98+
<label for="queue-concurrency-input-search" class="col-sm-8 col-form-label">Concurrency</label>
99+
<div class="col-sm-4">
100+
<input type="number" class="js-update-meta-concurrency form-control input-sm" style="margin-right: 10px;"
101+
placeholder="Concurrency"
102+
>
103+
</div>
104+
</div>
105+
<div class="form-group row">
106+
<label for="queue-rl-max-input-search" class="col-sm-8 col-form-label">Rate Limit Max</label>
107+
<div class="col-sm-4">
108+
<input type="number" class="js-update-meta-rl-max form-control input-sm" style="margin-right: 10px;"
109+
placeholder="Max"
110+
>
111+
</div>
112+
</div>
113+
<div class="form-group row">
114+
<label for="queue-rl-duration-input-search" class="col-sm-8 col-form-label">Rate Limit Duration</label>
115+
<div class="col-sm-4">
116+
<input type="number" class="js-update-meta-rl-duration form-control input-sm" style="margin-right: 10px;"
117+
placeholder="Duration"
118+
>
119+
</div>
120+
</div>
121+
<div class="js-update-queue-meta btn btn-primary btn-sm">
122+
Update
123+
</div>
124+
</div>
125+
<table class="meta-table table">
96126
{{#each globalConfig}}
97127
<tr>
98128
<th>{{ @key }}</th>

0 commit comments

Comments
 (0)