moved sending mentions to job (#16234)
refs TryGhost/Team#2523 -implemented jobsService within mention sending service -updated tests so we don't need to sleep
This commit is contained in:
parent
0d7944861c
commit
6c97edec25
@ -88,7 +88,16 @@ module.exports = {
|
||||
externalRequest,
|
||||
getSiteUrl: () => urlUtils.urlFor('home', true),
|
||||
getPostUrl: post => getPostUrl(post),
|
||||
isEnabled: () => !settingsCache.get('is_private')
|
||||
isEnabled: () => !settingsCache.get('is_private'),
|
||||
jobService: {
|
||||
async addJob(name, fn) {
|
||||
jobsService.addJob({
|
||||
name,
|
||||
job: fn,
|
||||
offloaded: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
sendingService.listen(events);
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ const {agentProvider, fixtureManager, mockManager} = require('../../utils/e2e-fr
|
||||
const sinon = require('sinon');
|
||||
const nock = require('nock');
|
||||
const assert = require('assert');
|
||||
const sleep = require('../../utils/sleep');
|
||||
const markdownToMobiledoc = require('../../utils/fixtures/data-generator').markdownToMobiledoc;
|
||||
const dnsPromises = require('dns').promises;
|
||||
const jobsService = require('../../../core/server/services/jobs');
|
||||
|
||||
let agent;
|
||||
let mentionUrl = new URL('https://www.otherghostsite.com/');
|
||||
@ -19,9 +19,6 @@ const mentionsPost = {
|
||||
mobiledoc: markdownToMobiledoc(mentionHtml)
|
||||
};
|
||||
|
||||
// NOTE: we need to sleep after the API calls because there's a race condition between the nock'd http response and the mentions service
|
||||
// TODO: move the mentions service to a jobbed process so we can await it
|
||||
|
||||
describe('Mentions Service', function () {
|
||||
before(async function () {
|
||||
agent = await agentProvider.getAdminAPIAgent();
|
||||
@ -47,7 +44,7 @@ describe('Mentions Service', function () {
|
||||
.reply(201);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
afterEach(async function () {
|
||||
mockManager.restore();
|
||||
nock.cleanAll();
|
||||
});
|
||||
@ -84,32 +81,36 @@ describe('Mentions Service', function () {
|
||||
|
||||
describe(`does send when we expect it to send`, function () {
|
||||
it('Newly published post (post.published)', async function () {
|
||||
let sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
|
||||
let publishedPost = {status: 'published', ...mentionsPost};
|
||||
await agent
|
||||
.post('posts/')
|
||||
.body({posts: [publishedPost]})
|
||||
.expectStatus(201);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
assert.equal(mentionMock.isDone(), true);
|
||||
assert.equal(endpointMock.isDone(), true);
|
||||
});
|
||||
|
||||
it('Edited published post (post.published.edited)', async function () {
|
||||
let sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let publishedPost = {status: 'published', ...mentionsPost};
|
||||
let res = await agent
|
||||
.post('posts/')
|
||||
.body({posts: [publishedPost]})
|
||||
.expectStatus(201);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
// while not the point of the test, we should have real links/mentions to start with
|
||||
assert.equal(mentionMock.isDone(), true);
|
||||
assert.equal(endpointMock.isDone(), true);
|
||||
|
||||
// reset mocks for mention
|
||||
sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let mentionMockTwo = nock(mentionUrl.href)
|
||||
.get('/')
|
||||
.reply(200, targetHtml, {'content-type': 'text/html'});
|
||||
@ -127,26 +128,28 @@ describe('Mentions Service', function () {
|
||||
.body({posts: [editedPost]})
|
||||
.expectStatus(200);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
assert.equal(mentionMockTwo.isDone(), true);
|
||||
assert.equal(endpointMockTwo.isDone(), true);
|
||||
});
|
||||
|
||||
it('Unpublished post (post.unpublished)', async function () {
|
||||
let sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let publishedPost = {status: 'published', ...mentionsPost};
|
||||
let res = await agent
|
||||
.post('posts/')
|
||||
.body({posts: [publishedPost]})
|
||||
.expectStatus(201);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
// while not the point of the test, we should have real links/mentions to start with
|
||||
assert.equal(mentionMock.isDone(), true);
|
||||
assert.equal(endpointMock.isDone(), true);
|
||||
|
||||
// reset mocks for mention
|
||||
sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let mentionMockTwo = nock(mentionUrl.href)
|
||||
.get('/')
|
||||
.reply(200, targetHtml, {'content-type': 'text/html'});
|
||||
@ -164,26 +167,28 @@ describe('Mentions Service', function () {
|
||||
.body({posts: [unpublishedPost]})
|
||||
.expectStatus(200);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
assert.equal(mentionMockTwo.isDone(), true);
|
||||
assert.equal(endpointMockTwo.isDone(), true);
|
||||
});
|
||||
|
||||
it('Sends for links that got removed from a post', async function () {
|
||||
let sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let publishedPost = {status: 'published', ...mentionsPost};
|
||||
let res = await agent
|
||||
.post('posts/')
|
||||
.body({posts: [publishedPost]})
|
||||
.expectStatus(201);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
// while not the point of the test, we should have real links/mentions to start with
|
||||
assert.equal(mentionMock.isDone(), true);
|
||||
assert.equal(endpointMock.isDone(), true);
|
||||
|
||||
// reset mocks for mention
|
||||
sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let mentionMockTwo = nock(mentionUrl.href)
|
||||
.get('/')
|
||||
.reply(200, targetHtml, {'content-type': 'text/html'});
|
||||
@ -200,7 +205,7 @@ describe('Mentions Service', function () {
|
||||
.body({posts: [editedPost]})
|
||||
.expectStatus(200);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
assert.equal(mentionMockTwo.isDone(), true);
|
||||
assert.equal(endpointMockTwo.isDone(), true);
|
||||
@ -208,13 +213,14 @@ describe('Mentions Service', function () {
|
||||
|
||||
// there's no special handling for this atm, but could be down the road
|
||||
it('New paid post', async function () {
|
||||
let sendWebmentionsJob = jobsService.awaitCompletion('sendWebmentions');
|
||||
let publishedPost = {status: 'published', visibility: 'paid', ...mentionsPost};
|
||||
await agent
|
||||
.post('posts/')
|
||||
.body({posts: [publishedPost]})
|
||||
.expectStatus(201);
|
||||
|
||||
await sleep(10);
|
||||
await sendWebmentionsJob;
|
||||
|
||||
assert.equal(mentionMock.isDone(), true);
|
||||
assert.equal(endpointMock.isDone(), true);
|
||||
|
@ -7,13 +7,15 @@ module.exports = class MentionSendingService {
|
||||
#getSiteUrl;
|
||||
#getPostUrl;
|
||||
#isEnabled;
|
||||
#jobService;
|
||||
|
||||
constructor({discoveryService, externalRequest, getSiteUrl, getPostUrl, isEnabled}) {
|
||||
constructor({discoveryService, externalRequest, getSiteUrl, getPostUrl, isEnabled, jobService}) {
|
||||
this.#discoveryService = discoveryService;
|
||||
this.#externalRequest = externalRequest;
|
||||
this.#getSiteUrl = getSiteUrl;
|
||||
this.#getPostUrl = getPostUrl;
|
||||
this.#isEnabled = isEnabled;
|
||||
this.#jobService = jobService;
|
||||
}
|
||||
|
||||
get siteUrl() {
|
||||
@ -57,10 +59,12 @@ module.exports = class MentionSendingService {
|
||||
// Post should be or should have been published
|
||||
return;
|
||||
}
|
||||
await this.sendAll({
|
||||
url: new URL(this.#getPostUrl(post)),
|
||||
html: post.get('html'),
|
||||
previousHtml: post.previous('status') === 'published' ? post.previous('html') : null
|
||||
await this.#jobService.addJob('sendWebmentions', async () => {
|
||||
await this.sendAll({
|
||||
url: new URL(this.#getPostUrl(post)),
|
||||
html: post.get('html'),
|
||||
previousHtml: post.previous('status') === 'published' ? post.previous('html') : null
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
logging.error('Error in webmention sending service post update event handler:');
|
||||
|
@ -7,6 +7,13 @@ const sinon = require('sinon');
|
||||
const logging = require('@tryghost/logging');
|
||||
const {createModel} = require('./utils/index.js');
|
||||
|
||||
// mock up job service
|
||||
let jobService = {
|
||||
async addJob(name, fn) {
|
||||
return fn();
|
||||
}
|
||||
};
|
||||
|
||||
describe('MentionSendingService', function () {
|
||||
let errorLogStub;
|
||||
|
||||
@ -124,7 +131,8 @@ describe('MentionSendingService', function () {
|
||||
it('Sends on publish', async function () {
|
||||
const service = new MentionSendingService({
|
||||
isEnabled: () => true,
|
||||
getPostUrl: () => 'https://site.com/post/'
|
||||
getPostUrl: () => 'https://site.com/post/',
|
||||
jobService: jobService
|
||||
});
|
||||
const stub = sinon.stub(service, 'sendAll');
|
||||
await service.sendForPost(createModel({
|
||||
@ -145,7 +153,8 @@ describe('MentionSendingService', function () {
|
||||
it('Sends on html change', async function () {
|
||||
const service = new MentionSendingService({
|
||||
isEnabled: () => true,
|
||||
getPostUrl: () => 'https://site.com/post/'
|
||||
getPostUrl: () => 'https://site.com/post/',
|
||||
jobService: jobService
|
||||
});
|
||||
const stub = sinon.stub(service, 'sendAll');
|
||||
await service.sendForPost(createModel({
|
||||
@ -265,7 +274,8 @@ describe('MentionSendingService', function () {
|
||||
getSiteUrl: () => new URL('https://site.com'),
|
||||
discoveryService: {
|
||||
getEndpoint: async () => new URL('https://example.org/webmentions-test')
|
||||
}
|
||||
},
|
||||
jobService: jobService
|
||||
});
|
||||
await service.sendAll({url: new URL('https://site.com'),
|
||||
html: `<a href="https://example.com">Example</a>`,
|
||||
|
Loading…
Reference in New Issue
Block a user