| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- import gql from 'graphql-tag';
- import path from 'path';
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
- import { initialData } from '../../../e2e-common/e2e-initial-data';
- import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
- import { createTestEnvironment } from '../../testing/lib/create-test-environment';
- import { SlowMutationPlugin } from './fixtures/test-plugins/slow-mutation-plugin';
- import * as Codegen from './graphql/generated-e2e-admin-types';
- import { LanguageCode } from './graphql/generated-e2e-admin-types';
- import {
- ADD_OPTION_GROUP_TO_PRODUCT,
- CREATE_PRODUCT,
- CREATE_PRODUCT_OPTION_GROUP,
- CREATE_PRODUCT_VARIANTS,
- } from './graphql/shared-definitions';
- describe('Parallel transactions', () => {
- const { server, adminClient, shopClient } = createTestEnvironment({
- ...testConfig(),
- plugins: [SlowMutationPlugin],
- });
- beforeAll(async () => {
- await server.init({
- initialData,
- productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
- customerCount: 2,
- });
- await adminClient.asSuperAdmin();
- }, TEST_SETUP_TIMEOUT_MS);
- afterAll(async () => {
- await server.destroy();
- });
- it('does not fail on many concurrent, slow transactions', async () => {
- const CONCURRENCY_LIMIT = 20;
- const slowMutations = Array.from({ length: CONCURRENCY_LIMIT }).map(i =>
- adminClient.query(SLOW_MUTATION, { delay: 50 }),
- );
- const result = await Promise.all(slowMutations);
- expect(result).toEqual(Array.from({ length: CONCURRENCY_LIMIT }).map(() => ({ slowMutation: true })));
- }, 100000);
- it('does not fail on attempted deadlock', async () => {
- const CONCURRENCY_LIMIT = 4;
- const slowMutations = Array.from({ length: CONCURRENCY_LIMIT }).map(i =>
- adminClient.query(ATTEMPT_DEADLOCK),
- );
- const result = await Promise.all(slowMutations);
- expect(result).toEqual(
- Array.from({ length: CONCURRENCY_LIMIT }).map(() => ({ attemptDeadlock: true })),
- );
- }, 100000);
- // A real-world error-case originally reported in https://github.com/vendurehq/vendure/issues/527
- it('does not deadlock on concurrent creating ProductVariants', async () => {
- const CONCURRENCY_LIMIT = 4;
- const { createProduct } = await adminClient.query<
- Codegen.CreateProductMutation,
- Codegen.CreateProductMutationVariables
- >(CREATE_PRODUCT, {
- input: {
- translations: [
- { languageCode: LanguageCode.en, name: 'Test', slug: 'test', description: 'test' },
- ],
- },
- });
- const sizes = Array.from({ length: CONCURRENCY_LIMIT }).map(i => `size-${i as string}`);
- const { createProductOptionGroup } = await adminClient.query<
- Codegen.CreateProductOptionGroupMutation,
- Codegen.CreateProductOptionGroupMutationVariables
- >(CREATE_PRODUCT_OPTION_GROUP, {
- input: {
- code: 'size',
- options: sizes.map(size => ({
- code: size,
- translations: [{ languageCode: LanguageCode.en, name: size }],
- })),
- translations: [{ languageCode: LanguageCode.en, name: 'size' }],
- },
- });
- await adminClient.query<
- Codegen.AddOptionGroupToProductMutation,
- Codegen.AddOptionGroupToProductMutationVariables
- >(ADD_OPTION_GROUP_TO_PRODUCT, {
- productId: createProduct.id,
- optionGroupId: createProductOptionGroup.id,
- });
- const createVariantMutations = createProductOptionGroup.options
- .filter((_, index) => index < CONCURRENCY_LIMIT)
- .map((option, i) => {
- return adminClient.query<
- Codegen.CreateProductVariantsMutation,
- Codegen.CreateProductVariantsMutationVariables
- >(CREATE_PRODUCT_VARIANTS, {
- input: [
- {
- sku: `VARIANT-${i}`,
- productId: createProduct.id,
- optionIds: [option.id],
- translations: [{ languageCode: LanguageCode.en, name: `Variant ${i}` }],
- price: 1000,
- taxCategoryId: 'T_1',
- facetValueIds: ['T_1', 'T_2'],
- featuredAssetId: 'T_1',
- assetIds: ['T_1'],
- },
- ],
- });
- });
- const results = await Promise.all(createVariantMutations);
- expect(results.length).toBe(CONCURRENCY_LIMIT);
- }, 100000);
- });
- const SLOW_MUTATION = gql`
- mutation SlowMutation($delay: Int!) {
- slowMutation(delay: $delay)
- }
- `;
- const ATTEMPT_DEADLOCK = gql`
- mutation AttemptDeadlock {
- attemptDeadlock
- }
- `;
|