bree
bree copied to clipboard
[fix] Unexpected high CPU use with 1s interval job
Describe the bug
Node.js version: v16.17.0
OS version: Docker node:16-bullseye-slim
Description: Just started using Bree to schedule some jobs inside a Docker container. Today I was working on a job that runs every 1s. I noticed that the job runner was using unusually high CPU for a very simple job. If I run my job in a while loop with a 1s sleep, it uses barely any CPU. If I run it using Bree, the job runner will consistently use 20-40% CPU.
Actual behavior
High CPU use.
Expected behavior
Much lower CPU use.
Code to reproduce
Here's the entire job runner:
const Bree = require('bree');
const Graceful = require('@ladjs/graceful');
const logger = require('./logger'); // this is just winston going to console
const bree = new Bree({
jobs: [
{
name: 'aggregate-icecast-status',
interval: '1s',
},
],
logger,
});
const graceful = new Graceful({ brees: [bree] });
graceful.listen();
(async () => {
logger.error('starting...');
await bree.start();
})();
Here's the job:
const { forEach } = require('modern-async');
const dns = require('dns').promises;
const fetch = require('node-fetch');
const Redis = require('ioredis');
const logger = require('../logger').child({
extraInfo: 'aggregate-icecast-status',
});
const redis = new Redis({
host: 'redis',
keyPrefix: 'ngradio:status:',
});
const resolver = new dns.Resolver();
async function main() {
logger.debug('aggregating icecast status');
let addresses;
try {
addresses = await resolver.resolve4('icecast');
} catch (err) {
logger.warn(`error resolving Icecast hosts: ${err.message}`);
return;
}
logger.debug('Icecast addresses: %o', addresses);
let totalListeners = 0;
let listenersPerHost = new Map();
let listenerPeaksPerHost = new Map();
let title;
await forEach(addresses, async (address) => {
logger.debug(`fetching status from ${address}`);
let data;
let response;
try {
response = await fetch(`http://${address}:8000/status-json.xsl`);
data = await response.json();
// logger.debug('%o', data);
} catch (err) {
logger.warn(`erroring collecting status from ${address}: ${err.message}`);
return;
}
const listeners = parseInt(data?.mounts?.['/radio.mp3']?.listeners, 10);
const listenerPeak = parseInt(
data?.mounts?.['/radio.mp3']?.listener_peak,
10
);
if (!title) {
title = data?.mounts?.['/radio.mp3']?.title;
}
if (isNaN(listeners)) {
logger.warn(`error parsing response from ${address}: listeners was NaN`);
} else {
totalListeners += listeners;
listenersPerHost.set(address, listeners);
}
if (isNaN(listenerPeak)) {
logger.warn(
`error parsing response from ${address}: listener peak was NaN`
);
} else {
listenerPeaksPerHost.set(address, listenerPeak);
}
});
await redis.del('listenerPeaksPerHost');
await redis.del('listenersPerHost');
await redis.hset('listenerPeaksPerHost', listenerPeaksPerHost);
await redis.hset('listenersPerHost', listenersPerHost);
await redis.set('totalListeners', totalListeners, 'EX', 5);
await redis.set('title', title, 'EX', 5);
logger.debug(
'Total listeners: %d, Listener peaks: %o, Listeners per host: %o, ' +
'title: "%s"',
totalListeners,
listenerPeaksPerHost,
listenersPerHost,
title
);
await redis.quit();
}
(async () => {
await main();
})();
Checklist
- [X] I have searched through GitHub issues for similar issues.
- [X] I have completely read through the README and documentation.
- [X] I have tested my code with the latest version of Node.js and this package and confirmed it is still not working.