-
Notifications
You must be signed in to change notification settings - Fork 1
Implemented ACID transaction support for atomic Clan creation #757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added some comments in files. Regarding to add deleteMany() in all of services in clanInventory module, just keep those as before and only need to add session?: ClientSession in each. But overall, you did very well. :D
After all, I got an error showing about TransactionCommitError by running test src/__tests__/clan/ClanService/createOne.test.ts. I don't know if you will get the same error, here is how I fixed:
let clanService: ClanService;
const clanCreateBuilder = ClanBuilderFactory.getBuilder('CreateClanDto');
const clanModel = ClanModule.getClanModel();
const playerModel = PlayerModule.getPlayerModel();
const stockModel = StockModule.getStockModel();
const itemModel = ItemModule.getItemModel();
const soulHomeModel = SoulhomeModule.getSoulhomeModel();
const loggedPlayer = LoggedUser.getPlayer();
const clanName = 'clan1';
const clanToCreate = clanCreateBuilder.setName(clanName).build();
beforeEach(async () => {
clanService = await ClanModule.getClanService();
await stockModel.deleteMany();
await itemModel.deleteMany();
await soulHomeModel.deleteMany();
});|
I've tried to re-use /**
* Deletes an Item by its _id from DB.
*
* @param _id - The Mongo _id of the Item to delete.
* @param options - Optional mongoose ClientSession for transaction support.
* @returns _true_ if Item was removed successfully, or a ServiceError array if the Item was not found or something else went wrong
*/
async deleteOneById(_id: string, options?: TIServiceDeleteByIdOptions) {
return this.basicService.deleteOneById(_id, options);
}
/**
* Deletes all Items of the specified by _id Stock from DB.
*
* @param stock_id - The Mongo _id of the Stock to delete all Items from.
* @param options - Optional mongoose ClientSession for transaction support.
* @returns _true_ if Items were removed successfully, or a ServiceError array if the Items were not found or something else went wrong
*/
async deleteAllStockItems(stock_id: string, options?: TIServiceDeleteByIdOptions) {
return this.basicService.deleteMany({
filter: { stock_id },
...options,
});
}
/**
* Deletes all Items of the specified by _id Room from DB.
*
* @param room_id - The Mongo _id of the Room from which all items should be deleted
* @param options - Optional mongoose ClientSession for transaction support.
* @returns _true_ if Items were removed successfully, or a ServiceError array if the Items were not found or something else went wrong
*/
async deleteAllRoomItems(room_id: string, options?: TIServiceDeleteByIdOptions) {
return this.basicService.deleteMany({
filter: { room_id },
...options,
});
} |
Closes #744
Brief description
This PR finally implements MongoDB transaction support for the Clan creation process. Previously, creating a Clan and its associated entities (SoulHome, Rooms, Stock) happened in separate database calls, which could lead to "orphaned" documents if a failure occurred mid-process.
I have refactored the Clan module and its dependencies to use a "Session Propagation" pattern. This ensures that the Clan, its roles, the leader's assignment, the SoulHome, the Stock, and all 30 initial Rooms are created as a single atomic unit. If any part fails, the entire operation is rolled back.
Technical highlights
Session Propagation: Updated the
BasicServiceand specific domain services to accept an optionalClientSession, allowing the same transaction to span multiple services.Atomic (all or nothing) Room Generation: Ensured the batch creation of 30 rooms is bound to the parent transaction.
Service Refactoring: Migrated the "Baton Pass" logic from
ClanServicethroughClanHelperServicedown to individual inventory services.Change list
src/clan/clan.service.ts: Initiates themongoSessionand manages thecommitTransaction/abortTransactionlifecycle.src/clan/utils/clanHelper.service.ts: Refactored to pass the session into plugin creation methods.src/common/service/basicService/BasicService.ts: Updated to support optional session parameters in core database operations.src/clanInventory/(Item, Room, SoulHome, Stock services): UpdatedcreateOneand related methods to support transactional execution.src/tests/.../LeaderboardService.test.ts: Cleaned up test logic to ensure compatibility with recent service changes.Verification results (Postman)
All service-level tests passed.
Total: 1153 tests passed.
Success Path: Creating a Clan successfully generates all 30 rooms and links the player in a single commit.
Rollback Path: Verified that if validation fails (e.g., invalid labels), no Clan or Room documents are persisted in the database, confirming the transaction aborts correctly.