Skip to content

Commit

Permalink
Fixes scheduled entries (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmerfield committed Mar 11, 2021
1 parent 1dbcd7f commit 9679892
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 36 deletions.
13 changes: 13 additions & 0 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ if (cluster.isMaster) {
const NUMBER_OF_WORKERS =
NUMBER_OF_CORES > 4 ? Math.round(NUMBER_OF_CORES / 2) : 2;
const scheduler = require("./scheduler");
const publishScheduledEntries = require("./scheduler/publish-scheduled-entries");

console.log(
clfdate(),
Expand All @@ -30,6 +31,12 @@ if (cluster.isMaster) {
if (worker.exitedAfterDisconnect === false) {
console.log(clfdate(), "Worker died unexpectedly, starting a new one");
cluster.fork();
// 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();
}
});

Expand Down Expand Up @@ -82,6 +89,12 @@ if (cluster.isMaster) {
},
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();
}
);
});
Expand Down
43 changes: 7 additions & 36 deletions app/scheduler/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
var Entries = require("entries");
var Entry = require("entry");
var User = require("user");
var async = require("async");
var Blog = require("blog");
var backup = require("./backup");
var dailyUpdate = require("./daily");
var helper = require("helper");
Expand All @@ -11,15 +8,19 @@ var clfdate = require("helper").clfdate;
var warmCache = require("./warmCache");
var schedule = require("node-schedule").scheduleJob;
var checkFeatuedSites = require("../brochure/routes/featured/check");
var publishScheduledEntries = require("./publish-scheduled-entries");

module.exports = function () {
// Bash the cache for scheduled posts
cacheScheduler(function (stat) {
console.log(clfdate(), stat);
publishScheduledEntries(function (err) {
if (err) throw err;
console.log(clfdate(), "Scheduled entries for future publication");
});

// Warm the cache for the brochure site
warmCache(function (err) {});
warmCache(function (err) {
if (err) throw err;
});

// Warn users about impending subscriptions
User.getAllIds(function (err, uids) {
Expand Down Expand Up @@ -109,33 +110,3 @@ module.exports = function () {
});
});
};

function cacheScheduler(callback) {
var totalScheduled = 0;

Blog.getAllIDs(function (err, blogIDs) {
async.each(
blogIDs,
function (blogID, nextBlog) {
Entries.get(blogID, { lists: ["scheduled"] }, function (err, list) {
async.each(
list.scheduled,
function (futureEntry, nextEntry) {
totalScheduled++;

// Saving empty updates will call the entry scheduler
// and ensure the entry is rebuilt again in future
Entry.set(blogID, futureEntry.path, {}, nextEntry);
},
function () {
nextBlog();
}
);
});
},
function () {
callback("Scheduled " + totalScheduled + " posts to clear the cache.");
}
);
});
}
30 changes: 30 additions & 0 deletions app/scheduler/publish-scheduled-entries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const Entries = require("models/entries");
const Entry = require("models/entry");
const Blog = require("models/blog");
const async = require("async");

function publishScheduledEntries(callback = function () {}) {
Blog.getAllIDs(function (err, blogIDs) {
if (err) return callback(err);
async.each(
blogIDs,
function (blogID, nextBlog) {
Entries.get(blogID, { lists: ["scheduled"] }, function (err, list) {
if (err) return callback(err);
async.each(
list.scheduled,
function (futureEntry, nextEntry) {
// Saving an update, even an empty one, will ensure the entry model
// schedules a task to rebuild the entry again in future when it's
// time to publish the entry.
Entry.set(blogID, futureEntry.path, {}, nextEntry);
},
nextBlog
);
});
},
callback
);
});
}
module.exports = publishScheduledEntries;
96 changes: 96 additions & 0 deletions tests/blog/scheduled-post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Enable this test once we can run it in parallel
// it's too slow otherwise
xdescribe("scheduled posts", function () {
const Template = require("models/template");
const Blog = require("models/blog");
const sync = require("sync");
const blogServer = require("blog");
const fs = require("fs-extra");
const request = require("request");
const Express = require("express");
const config = require("../../config");
const guid = require("helper").guid;
const moment = require("moment");
const MINUTE = 60 * 1000;

global.test.blog();

it(
"are published",
function (done) {
const path = "/entry.txt";
const id = guid();
sync(this.blog.id, (err, folder, finish) => {
if (err) return callback(err);
const contents = `Date: ${moment()
.utc()
.add(1, "minutes")
.format("YYYY-MM-DD HH:mm")}\n\n${id}`;
setTimeout(() => {
request(this.origin, { strictSSL: false }, (err, res, body) => {
expect(body).toContain(id);
done();
});
}, MINUTE);
fs.outputFileSync(this.blogDirectory + path, contents, "utf-8");
folder.update(path, (err) => {
if (err) return callback(err);
finish(null, () => {
request(this.origin, { strictSSL: false }, (err, res, body) => {
expect(body).not.toContain(id);
});
});
});
});
},
MINUTE * 2
);

beforeEach(function (done) {
const templateName = "example";

const view = {
name: "entries.html",
content: `<html><head></head><body>{{#entries}}{{{html}}}{{/entries}}</body></html>`,
};

Template.create(this.blog.id, templateName, {}, (err) => {
if (err) return done(err);
Template.getTemplateList(this.blog.id, (err, templates) => {
let templateId = templates.filter(
({ name }) => name === templateName
)[0].id;
Template.setView(templateId, view, (err) => {
if (err) return done(err);
Blog.set(
this.blog.id,
{ forceSSL: false, template: templateId },
done
);
});
});
});
});

// Create a webserver for testing remote files
beforeEach(function (done) {
this.server = Express()
.use((req, res, next) => {
const _get = req.get;
req.get = (arg) => {
if (arg === "host") {
return `${this.blog.handle}.${config.host}`;
} else return _get(arg);
};
next();
})
.use(blogServer)
.listen(8919, done);
this.origin = "http://localhost:" + 8919;
});

afterEach(function (done) {
this.server.close();
done();
});
});

0 comments on commit 9679892

Please sign in to comment.