import { randomUUID } from 'node:crypto'; import { identityApp, type IdentityApp } from './helpers/identity-app'; import { checkoutFixture, couponInput } from './helpers/checkout'; import { secondActor, addressInput } from './helpers/commerce'; const native = process.env.TEST_DATABASE_URL ? describe : describe.skip; native('native PostgreSQL checkout concurrency', () => { let ctx: IdentityApp; beforeAll(async () => { ctx = await identityApp(); }, 60000); afterAll(async () => { await ctx.close(); }); beforeEach(async () => { await ctx.clearLimits(); }); it('creates one order for two simultaneous identical requests', async () => { const f = await checkoutFixture(ctx); const responses = await Promise.all( [1, 2].map(() => ctx .api() .post('/api/v1/checkout') .auth(f.actor.token, { type: 'bearer' }) .send(f.input), ), ); expect(responses.map((response) => response.status)).toEqual([201, 201]); expect(responses[0]!.body.id).toBe(responses[1]!.body.id); expect( await ctx.db.stockReservation.count({ where: { userId: f.actor.userId }, }), ).toBe(1); }); it('lets only one competing checkout claim the final stock and coupon use', async () => { const f = await checkoutFixture(ctx, 2); const other = await secondActor(ctx); const address = await ctx .api() .post('/api/v1/addresses') .auth(other.token, { type: 'bearer' }) .send(addressInput) .expect(201); await ctx .api() .put('/api/v1/cart/lines/' + f.variant.id) .auth(other.token, { type: 'bearer' }) .send({ quantity: 2, version: 0 }) .expect(200); const coupon = await ctx .api() .post('/api/v1/coupons') .auth(ctx.token, { type: 'bearer' }) .send({ ...couponInput(), maxUses: 1 }) .expect(201); const commands = [ { actor: f.actor, input: { ...f.input, couponCode: coupon.body.code } }, { actor: other, input: { ...f.input, addressId: address.body.id, idempotencyKey: randomUUID(), couponCode: coupon.body.code, }, }, ]; const responses = await Promise.all( commands.map(({ actor, input }) => ctx .api() .post('/api/v1/checkout') .auth(actor.token, { type: 'bearer' }) .send(input), ), ); expect(responses.map((response) => response.status).sort()).toEqual([ 201, 409, ]); expect( await ctx.db.order.count({ where: { couponId: coupon.body.id } }), ).toBe(1); const reserved = await ctx.db.stockReservation.aggregate({ where: { stockItemId: f.stock.id }, _sum: { quantity: true }, }); expect(reserved._sum.quantity).toBe(2); }); it('coordinates checkout with a standalone inventory reservation', async () => { const f = await checkoutFixture(ctx, 2); const responses = await Promise.all([ ctx .api() .post('/api/v1/checkout') .auth(f.actor.token, { type: 'bearer' }) .send(f.input), ctx .api() .post('/api/v1/inventory/reservations') .auth(ctx.token, { type: 'bearer' }) .send({ stockItemId: f.stock.id, quantity: 2, idempotencyKey: randomUUID(), }), ]); expect(responses.map((response) => response.status).sort()).toEqual([ 201, 409, ]); const held = await ctx.db.stockReservation.aggregate({ where: { stockItemId: f.stock.id }, _sum: { quantity: true }, }); expect(held._sum.quantity).toBe(2); }); });