0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00

Extracted post/page cache invalidation logic to service

refs https://github.com/TryGhost/Team/issues/949

- The code is exactly the same in six (!) places. It's beyond unmaintainable to add another line to any of these place, which will be needed for `email_only` handling.
- The newly created posts service is a temporary, slightly better solution that complies with codebase's best practice of extracting new services using class with DI pattern
This commit is contained in:
Naz 2021-08-05 14:51:47 +04:00
parent accf0c645a
commit 15073bad29
7 changed files with 99 additions and 106 deletions

View file

@ -2,9 +2,18 @@ const models = require('../../models');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const PostsService = require('../../services/posts/posts-service');
const ALLOWED_INCLUDES = ['tags', 'authors', 'authors.roles'];
const UNSAFE_ATTRS = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'canary',
mega: null,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'pages',
browse: {
@ -150,23 +159,7 @@ module.exports = {
async query(frame) {
const model = await models.Post.edit(frame.data.pages[0], frame.options);
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}

View file

@ -3,10 +3,18 @@ const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const {mega} = require('../../services/mega');
const {BadRequestError} = require('@tryghost/errors');
const PostsService = require('../../services/posts/posts-service');
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
const unsafeAttrs = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'canary',
mega: mega,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'posts',
browse: {
@ -209,24 +217,8 @@ module.exports = {
}
}
/**Handle cache invalidation */
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}
},

View file

@ -2,9 +2,18 @@ const models = require('../../models');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const PostsService = require('../../services/posts/posts-service');
const ALLOWED_INCLUDES = ['tags', 'authors', 'authors.roles'];
const UNSAFE_ATTRS = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'v2',
mega: null,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'pages',
browse: {
@ -147,23 +156,7 @@ module.exports = {
async query(frame) {
const model = await models.Post.edit(frame.data.pages[0], frame.options);
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}

View file

@ -2,9 +2,18 @@ const models = require('../../models');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const PostsService = require('../../services/posts/posts-service');
const allowedIncludes = ['tags', 'authors', 'authors.roles'];
const unsafeAttrs = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'v2',
mega: null,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'posts',
browse: {
@ -143,23 +152,7 @@ module.exports = {
async query(frame) {
const model = await models.Post.edit(frame.data.posts[0], frame.options);
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}

View file

@ -2,9 +2,18 @@ const models = require('../../models');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const PostsService = require('../../services/posts/posts-service');
const ALLOWED_INCLUDES = ['tags', 'authors', 'authors.roles'];
const UNSAFE_ATTRS = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'v3',
mega: null,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'pages',
browse: {
@ -150,23 +159,7 @@ module.exports = {
async query(frame) {
const model = await models.Post.edit(frame.data.pages[0], frame.options);
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}

View file

@ -3,10 +3,18 @@ const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const urlUtils = require('../../../shared/url-utils');
const {mega} = require('../../services/mega');
const {BadRequestError} = require('@tryghost/errors');
const PostsService = require('../../services/posts/posts-service');
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
const unsafeAttrs = ['status', 'authors', 'visibility'];
const postsService = new PostsService({
apiVersion: 'v3',
mega: mega,
urlUtils: urlUtils,
i18n: i18n,
models: models
});
module.exports = {
docName: 'posts',
browse: {
@ -209,24 +217,8 @@ module.exports = {
}
}
/**Handle cache invalidation */
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
this.headers.cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
this.headers.cacheInvalidate = {
value: urlUtils.urlFor({
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
this.headers.cacheInvalidate = false;
}
this.headers.cacheInvalidate = postsService.handleCacheInvalidation(model);
return model;
}
},

View file

@ -0,0 +1,37 @@
const {BadRequestError} = require('@tryghost/errors');
class PostsService {
constructor({mega, apiVersion, urlUtils, i18n, models}) {
this.apiVersion = apiVersion;
this.mega = mega;
this.urlUtils = urlUtils;
this.i18n = i18n;
this.models = models;
}
handleCacheInvalidation(model) {
let cacheInvalidate;
if (
model.get('status') === 'published' && model.wasChanged() ||
model.get('status') === 'draft' && model.previous('status') === 'published'
) {
cacheInvalidate = true;
} else if (
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
model.get('status') === 'scheduled' && model.wasChanged()
) {
cacheInvalidate = {
value: this.urlUtils.urlFor({
relativeUrl: this.urlUtils.urlJoin('/p', model.get('uuid'), '/')
})
};
} else {
cacheInvalidate = false;
}
return cacheInvalidate;
}
}
module.exports = PostsService;