Skip to content

Commit

Permalink
Merge pull request #15100 from Automattic/vkarpov15/gh-15091
Browse files Browse the repository at this point in the history
fix(model): throw error if calling `create()` with multiple docs in a transaction unless `ordered: true`
  • Loading branch information
vkarpov15 authored Dec 16, 2024
2 parents f8844bb + 2d51c10 commit b7191c4
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
4 changes: 4 additions & 0 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -2619,6 +2619,10 @@ Model.create = async function create(doc, options) {

delete options.aggregateErrors; // dont pass on the option to "$save"

if (options.session && !options.ordered && args.length > 1) {
throw new MongooseError('Cannot call `create()` with a session and multiple documents unless `ordered: true` is set');
}

if (options.ordered) {
for (let i = 0; i < args.length; i++) {
try {
Expand Down
49 changes: 48 additions & 1 deletion test/docs/transactions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,10 @@ describe('transactions', function() {
const session = await db.startSession();

session.startTransaction();
await Character.create([{ name: 'Will Riker', rank: 'Commander' }, { name: 'Jean-Luc Picard', rank: 'Captain' }], { session });
await Character.create([
{ name: 'Will Riker', rank: 'Commander' },
{ name: 'Jean-Luc Picard', rank: 'Captain' }
], { session, ordered: true });

let names = await Character.distinct('name', {}, { session });
assert.deepStrictEqual(names.sort(), ['Jean-Luc Picard', 'Will Riker']);
Expand Down Expand Up @@ -660,4 +663,48 @@ describe('transactions', function() {
const { name } = await Test.findById(_id);
assert.strictEqual(name, 'bar');
});

it('throws error if using `create()` with multiple docs in a transaction (gh-15091)', async function() {
const BookingSchema = new Schema({
user: mongoose.Types.ObjectId,
slot: mongoose.Types.ObjectId,
bookingFor: String,
moreInfo: String
});

// Create models
db.deleteModel(/Test/);
const Booking = db.model('Test', BookingSchema);

// Define a sample payload
const user = { userId: new mongoose.Types.ObjectId() };
const payload = {
slotId: new mongoose.Types.ObjectId(),
data: [
{ bookingFor: 'Person A', moreInfo: 'Some info' },
{ bookingFor: 'Person B', moreInfo: 'Other info' }
]
};

const session = await db.startSession();
session.startTransaction();

const bookingData = payload.data.map((obj) => ({
user: user.userId,
slot: payload.slotId,
bookingFor: obj.bookingFor,
moreInfo: obj.moreInfo
}));

const bookings = await Booking.create(bookingData, { session, ordered: true });
assert.equal(bookings.length, 2);

await assert.rejects(
Booking.create(bookingData, { session }),
/Cannot call `create\(\)` with a session and multiple documents unless `ordered: true` is set/
);

await session.abortTransaction();
await session.endSession();
});
});

0 comments on commit b7191c4

Please sign in to comment.