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

Wrapped collection's creation in transaction

refs https://github.com/TryGhost/Arch/issues/16

- This is needed to avoid stale data/race conditions when processing collection post updates
This commit is contained in:
Naz 2023-07-19 22:11:28 +08:00 committed by naz
parent 0880770d50
commit 3dc27f505c
2 changed files with 31 additions and 22 deletions

View file

@ -22,7 +22,7 @@ const messages = {
}; };
interface SlugService { interface SlugService {
generate(desired: string): Promise<string>; generate(desired: string, options: {transaction: any}): Promise<string>;
} }
type CollectionsServiceDeps = { type CollectionsServiceDeps = {
@ -190,30 +190,37 @@ export class CollectionsService {
} }
async createCollection(data: CollectionInputDTO): Promise<CollectionDTO> { async createCollection(data: CollectionInputDTO): Promise<CollectionDTO> {
const slug = await this.slugService.generate(data.slug || data.title); return await this.collectionsRepository.createTransaction(async (transaction) => {
const collection = await Collection.create({ const slug = await this.slugService.generate(data.slug || data.title, {
title: data.title, transaction: transaction
slug: slug, });
description: data.description, const collection = await Collection.create({
type: data.type, title: data.title,
filter: data.filter, slug: slug,
featureImage: data.feature_image, description: data.description,
deletable: data.deletable type: data.type,
}); filter: data.filter,
featureImage: data.feature_image,
if (collection.type === 'automatic' && collection.filter) { deletable: data.deletable
const posts = await this.postsRepository.getAll({
filter: collection.filter
}); });
for (const post of posts) { if (collection.type === 'automatic' && collection.filter) {
collection.addPost(post); const posts = await this.postsRepository.getAll({
filter: collection.filter,
transaction: transaction
});
for (const post of posts) {
collection.addPost(post);
}
} }
}
await this.collectionsRepository.save(collection); await this.collectionsRepository.save(collection, {
transaction: transaction
});
return this.toDTO(collection); return this.toDTO(collection);
});
} }
async addPostToCollection(collectionId: string, post: CollectionPostListItemDTO): Promise<CollectionDTO | null> { async addPostToCollection(collectionId: string, post: CollectionPostListItemDTO): Promise<CollectionDTO | null> {

View file

@ -19,8 +19,10 @@ class CollectionsServiceWrapper {
postsRepository: postsRepository, postsRepository: postsRepository,
DomainEvents: DomainEvents, DomainEvents: DomainEvents,
slugService: { slugService: {
async generate(input) { async generate(input, options) {
return models.Collection.generateSlug(models.Collection, input, {}); return models.Collection.generateSlug(models.Collection, input, {
transacting: options.transaction
});
} }
} }
}); });