Skip to content

Commit

Permalink
Remove clustering
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmerfield committed Jan 24, 2025
1 parent 8f08b30 commit f184c66
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 140 deletions.
161 changes: 22 additions & 139 deletions app/index.js
Original file line number Diff line number Diff line change
@@ -1,154 +1,37 @@
const cluster = require("cluster");
const config = require("config");

if (cluster.isMaster) {
const async = require("async");
const fs = require("fs-extra");
const clfdate = require("helper/clfdate");
const notify = require("helper/systemd-notify");
const clfdate = require("helper/clfdate");
const email = require("helper/email");
const scheduler = require("./scheduler");
const setup = require("./setup");
const server = require("./server");

// we used to fork multiple workers, but now we only fork one
// since we run multiple docker containers instead
// todo: remove this code
const NUMBER_OF_WORKERS = 1;

const publishScheduledEntries = require("./scheduler/publish-scheduled-entries");
console.log(clfdate(), `Starting server pid=${process.pid} environment=${config.environment}`);

// Open the server to handle requests
server.listen(config.port, function () {
console.log(
clfdate(),
`Starting pid=${process.pid} environment=${config.environment} workers=${NUMBER_OF_WORKERS}`
`Server listening pid=${process.pid} port=${config.port}`
);

// Write the master process PID so we can signal it
fs.outputFileSync(config.pidfile, process.pid.toString(), "utf-8");

for (let i = 0; i < NUMBER_OF_WORKERS; i++) {
cluster.fork();
}

const email = require("helper/email");

// It's important that this only runs once and 'listening'
// will fire when each worker comes online
cluster.once("listening", () => {
const scheduler = require("./scheduler");
const setup = require("./setup");
email.SERVER_START();

email.SERVER_START();
setup(async err => {
if (err) throw err;

setup(async err => {
if (err) throw err;
console.log(clfdate(), "Finished setting up server");

console.log(clfdate(), "Finished setting up");
// Launch scheduler for background tasks, like backups, emails
scheduler();

// Launch scheduler for background tasks, like backups, emails
scheduler();

// Run any initialization that clients need
// Google Drive will renew any webhooks, e.g.
for (const { init, display_name } of Object.values(require("clients"))) {
if (init) {
console.log(clfdate(), display_name + " client:", "Initializing");
init();
}
// Run any initialization that clients need
// Google Drive will renew any webhooks, e.g.
for (const { init, display_name } of Object.values(require("clients"))) {
if (init) {
console.log(clfdate(), display_name + " client:", "Initializing");
init();
}

notify({ ready: true, status: "Node server ready" });

setInterval(() => {
notify({
status: `Node server running ${
Object.keys(cluster.workers).length
} workers at ${new Date().toISOString()}}`
});
}, 1000 * 10); // every 10 seconds
});
});

cluster.on("exit", worker => {
if (worker.exitedAfterDisconnect === false) {
console.log(clfdate(), "Worker died unexpectedly, starting a new one");
cluster.fork();
email.WORKER_ERROR();
// worker processes can have scheduled tasks to publish
// scheduled entries in future – if the worker dies it's
// important the master process instead schedules the task
// todo: make it so that workers can ask the master
// process to deal with publication scheduling...
publishScheduledEntries();
}
});

// SIGUSR1 is used by node for debugging, so we use SIGUSR2 to
// signal the master process that it's time to reboot the servers
process.on("SIGUSR2", function () {
let workerIDs = Object.keys(cluster.workers);
let totalWorkers = workerIDs.length;

console.log(
clfdate(),
`Recieved signal to replace ${totalWorkers} workers`
);

async.eachSeries(
workerIDs,
function (workerID, next) {
let worker;
let workerIndex = workerIDs.indexOf(workerID) + 1;
let replacementWorker;
let timeout;

console.log(
clfdate(),
`Replacing worker ${workerIndex}/${totalWorkers}`
);

worker = cluster.workers[workerID];

worker.on("disconnect", function () {
clearTimeout(timeout);
});

worker.disconnect();

timeout = setTimeout(() => {
worker.kill();
}, 2000);

replacementWorker = cluster.fork();

replacementWorker.on("listening", function () {
console.log(
clfdate(),
`Replaced worker ${workerIndex}/${totalWorkers}`
);
workerID++;
next();
});
},
function () {
console.log(clfdate(), `Replaced all workers`);
// worker processes can have scheduled tasks to publish
// scheduled entries in future – if the worker dies it's
// important the master process instead schedules the task
// todo: make it so that workers can ask the master
// process to deal with publication scheduling...
publishScheduledEntries();
}
);
});
} else {
const clfdate = require("helper/clfdate");

console.log(clfdate(), `Worker process running pid=${process.pid}`);

const server = require("./server");

// Open the server to handle requests
server.listen(config.port, function () {
console.log(
clfdate(),
`Worker process listening pid=${process.pid} port=${config.port}`
);
});
}
});
2 changes: 1 addition & 1 deletion scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ DOCKER_RUN_COMMAND="docker run --pull=always -d \
--env-file /etc/blot/secrets.env \
-v /var/www/blot/data:/usr/src/app/data \
--restart unless-stopped \
--memory=1.5g --cpus=1 \
--memory=2g --cpus=1 \
ghcr.io/davidmerfield/blot:$GIT_COMMIT_HASH"

# Configurable health check timeout
Expand Down

0 comments on commit f184c66

Please sign in to comment.