mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-23 22:11:09 +03:00
Update of collection posts on bulk destroy
refs https://github.com/TryGhost/Arch/issues/16 - When the bulk destroy is done on posts Collections need to know about the update and remove the stored posts from collections.
This commit is contained in:
parent
ffa101b550
commit
9b257f3966
@ -7,6 +7,7 @@ import {MethodNotAllowedError} from '@tryghost/errors';
|
|||||||
import {PostDeletedEvent} from './events/PostDeletedEvent';
|
import {PostDeletedEvent} from './events/PostDeletedEvent';
|
||||||
import {PostAddedEvent} from './events/PostAddedEvent';
|
import {PostAddedEvent} from './events/PostAddedEvent';
|
||||||
import {PostEditedEvent} from './events/PostEditedEvent';
|
import {PostEditedEvent} from './events/PostEditedEvent';
|
||||||
|
import {PostsBulkDestroyedEvent} from '@tryghost/post-events';
|
||||||
import {RepositoryUniqueChecker} from './RepositoryUniqueChecker';
|
import {RepositoryUniqueChecker} from './RepositoryUniqueChecker';
|
||||||
import {TagDeletedEvent} from './events/TagDeletedEvent';
|
import {TagDeletedEvent} from './events/TagDeletedEvent';
|
||||||
|
|
||||||
@ -178,6 +179,11 @@ export class CollectionsService {
|
|||||||
await this.updatePostInMatchingCollections(event.data);
|
await this.updatePostInMatchingCollections(event.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.DomainEvents.subscribe(PostsBulkDestroyedEvent, async (event: PostsBulkDestroyedEvent) => {
|
||||||
|
logging.info(`BulkDestroyEvent received, removing posts ${event.data} from all collections`);
|
||||||
|
await this.removePostsFromAllCollections(event.data);
|
||||||
|
});
|
||||||
|
|
||||||
this.DomainEvents.subscribe(TagDeletedEvent, async (event: TagDeletedEvent) => {
|
this.DomainEvents.subscribe(TagDeletedEvent, async (event: TagDeletedEvent) => {
|
||||||
logging.info(`TagDeletedEvent received for ${event.data.id}, updating all collections`);
|
logging.info(`TagDeletedEvent received for ${event.data.id}, updating all collections`);
|
||||||
await this.updateAllAutomaticCollections();
|
await this.updateAllAutomaticCollections();
|
||||||
@ -269,6 +275,21 @@ export class CollectionsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async removePostsFromAllCollections(postIds: string[]) {
|
||||||
|
return await this.collectionsRepository.createTransaction(async (transaction) => {
|
||||||
|
const collections = await this.collectionsRepository.getAll({transaction});
|
||||||
|
|
||||||
|
for (const collection of collections) {
|
||||||
|
for (const postId of postIds) {
|
||||||
|
if (collection.includesPost(postId)) {
|
||||||
|
collection.removePost(postId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.collectionsRepository.save(collection, {transaction});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async addPostToMatchingCollections(post: CollectionPost) {
|
private async addPostToMatchingCollections(post: CollectionPost) {
|
||||||
return await this.collectionsRepository.createTransaction(async (transaction) => {
|
return await this.collectionsRepository.createTransaction(async (transaction) => {
|
||||||
const collections = await this.collectionsRepository.getAll({
|
const collections = await this.collectionsRepository.getAll({
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
PostEditedEvent,
|
PostEditedEvent,
|
||||||
TagDeletedEvent
|
TagDeletedEvent
|
||||||
} from '../src/index';
|
} from '../src/index';
|
||||||
|
import {PostsBulkDestroyedEvent} from '@tryghost/post-events';
|
||||||
import {PostsRepositoryInMemory} from './fixtures/PostsRepositoryInMemory';
|
import {PostsRepositoryInMemory} from './fixtures/PostsRepositoryInMemory';
|
||||||
import {posts as postFixtures} from './fixtures/posts';
|
import {posts as postFixtures} from './fixtures/posts';
|
||||||
import {CollectionPost} from '../src/CollectionPost';
|
import {CollectionPost} from '../src/CollectionPost';
|
||||||
@ -403,6 +404,25 @@ describe('CollectionsService', function () {
|
|||||||
assert.equal((await collectionsService.getById(manualCollection.id))?.posts.length, 1);
|
assert.equal((await collectionsService.getById(manualCollection.id))?.posts.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Updates all collections when posts are deleted in bulk', async function () {
|
||||||
|
assert.equal((await collectionsService.getById(automaticFeaturedCollection.id))?.posts?.length, 2);
|
||||||
|
assert.equal((await collectionsService.getById(automaticNonFeaturedCollection.id))?.posts.length, 2);
|
||||||
|
assert.equal((await collectionsService.getById(manualCollection.id))?.posts.length, 2);
|
||||||
|
|
||||||
|
collectionsService.subscribeToEvents();
|
||||||
|
const postDeletedEvent = PostsBulkDestroyedEvent.create([
|
||||||
|
posts[0].id,
|
||||||
|
posts[1].id
|
||||||
|
]);
|
||||||
|
|
||||||
|
DomainEvents.dispatch(postDeletedEvent);
|
||||||
|
await DomainEvents.allSettled();
|
||||||
|
|
||||||
|
assert.equal((await collectionsService.getById(automaticFeaturedCollection.id))?.posts?.length, 2);
|
||||||
|
assert.equal((await collectionsService.getById(automaticNonFeaturedCollection.id))?.posts.length, 0);
|
||||||
|
assert.equal((await collectionsService.getById(manualCollection.id))?.posts.length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
it('Updates only index collection when a non-featured post is added', async function () {
|
it('Updates only index collection when a non-featured post is added', async function () {
|
||||||
assert.equal((await collectionsService.getById(automaticFeaturedCollection.id))?.posts?.length, 2);
|
assert.equal((await collectionsService.getById(automaticFeaturedCollection.id))?.posts?.length, 2);
|
||||||
assert.equal((await collectionsService.getById(automaticNonFeaturedCollection.id))?.posts.length, 2);
|
assert.equal((await collectionsService.getById(automaticNonFeaturedCollection.id))?.posts.length, 2);
|
||||||
|
@ -4,6 +4,8 @@ const tpl = require('@tryghost/tpl');
|
|||||||
const errors = require('@tryghost/errors');
|
const errors = require('@tryghost/errors');
|
||||||
const ObjectId = require('bson-objectid').default;
|
const ObjectId = require('bson-objectid').default;
|
||||||
const pick = require('lodash/pick');
|
const pick = require('lodash/pick');
|
||||||
|
const DomainEvents = require('@tryghost/domain-events/lib/DomainEvents');
|
||||||
|
const {PostsBulkDestroyedEvent} = require('@tryghost/post-events');
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
invalidVisibilityFilter: 'Invalid visibility filter.',
|
invalidVisibilityFilter: 'Invalid visibility filter.',
|
||||||
@ -385,7 +387,12 @@ class PostsService {
|
|||||||
|
|
||||||
// Posts and emails
|
// Posts and emails
|
||||||
await this.models.Post.bulkDestroy(deleteEmailIds, 'emails', {transacting: options.transacting, throwErrors: true});
|
await this.models.Post.bulkDestroy(deleteEmailIds, 'emails', {transacting: options.transacting, throwErrors: true});
|
||||||
return await this.models.Post.bulkDestroy(deleteIds, 'posts', {...options, throwErrors: true});
|
const result = await this.models.Post.bulkDestroy(deleteIds, 'posts', {...options, throwErrors: true});
|
||||||
|
|
||||||
|
const event = PostsBulkDestroyedEvent.create(deleteIds);
|
||||||
|
DomainEvents.dispatch(event);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async export(frame) {
|
async export(frame) {
|
||||||
|
Loading…
Reference in New Issue
Block a user