diff --git a/app/api/entities/specs/routes.spec.ts b/app/api/entities/specs/routes.spec.ts index 97bdb31a40..955b7cd319 100644 --- a/app/api/entities/specs/routes.spec.ts +++ b/app/api/entities/specs/routes.spec.ts @@ -11,6 +11,7 @@ import { legacyLogger } from 'api/log'; import templates from 'api/templates'; import thesauri from 'api/thesauri'; import { appContext } from 'api/utils/AppContext'; +import { testingTenants } from 'api/utils/testingTenants'; import { UserInContextMockFactory } from 'api/utils/testingUserInContext'; import { ObjectId } from 'mongodb'; import path from 'path'; @@ -248,6 +249,7 @@ describe('entities routes', () => { }); it('should run saveEntity process as a transaction', async () => { + testingTenants.changeCurrentTenant({ featureFlags: { v1_transactions: true } }); jest.restoreAllMocks(); jest.spyOn(entities, 'getUnrestrictedWithDocuments').mockImplementationOnce(() => { throw new Error('error at the end of the saveEntity'); diff --git a/app/api/tenants/tenantContext.ts b/app/api/tenants/tenantContext.ts index 1b0ad037cb..619b8146e7 100644 --- a/app/api/tenants/tenantContext.ts +++ b/app/api/tenants/tenantContext.ts @@ -16,6 +16,7 @@ type Tenant = { featureFlags?: { s3Storage?: boolean; sync?: boolean; + v1_transactions?: boolean; }; globalMatomo?: { id: string; url: string }; ciMatomoActive?: boolean; diff --git a/app/api/utils/specs/withTransaction.spec.ts b/app/api/utils/specs/withTransaction.spec.ts index 882cc14e84..5b1022888d 100644 --- a/app/api/utils/specs/withTransaction.spec.ts +++ b/app/api/utils/specs/withTransaction.spec.ts @@ -13,6 +13,7 @@ import { elasticTesting } from '../elastic_testing'; import { getFixturesFactory } from '../fixturesFactory'; import { testingEnvironment } from '../testingEnvironment'; import { withTransaction } from '../withTransaction'; +import { testingTenants } from '../testingTenants'; const factory = getFixturesFactory(); @@ -48,6 +49,7 @@ describe('withTransaction utility', () => { beforeEach(async () => { await testingEnvironment.setUp({ transactiontests: [] }); + testingTenants.changeCurrentTenant({ featureFlags: { v1_transactions: true } }); testingEnvironment.unsetFakeContext(); }); @@ -167,6 +169,26 @@ describe('withTransaction utility', () => { }); }); + it('should do nothing when the feature flag is off when there is an error', async () => { + testingTenants.changeCurrentTenant({ featureFlags: { v1_transactions: false } }); + + await appContext.run(async () => { + let error: Error | undefined; + try { + await withTransaction(async () => { + await model.save({ title: 'test-flag-off', value: 1 }); + throw new Error('Testing error'); + }); + } catch (e) { + error = e; + } + expect(error?.message).toBe('Testing error'); + + const docs = await model.get({ title: 'test-flag-off' }); + expect(docs).toHaveLength(1); + }); + }); + describe('manual abort', () => { it('should allow manual abort without throwing error', async () => { await appContext.run(async () => { @@ -230,6 +252,19 @@ describe('withTransaction utility', () => { expect(sessionToTest?.hasEnded).toBe(true); }); }); + it('should do nothing when the feature flag is off', async () => { + testingTenants.changeCurrentTenant({ featureFlags: { v1_transactions: false } }); + + await appContext.run(async () => { + await withTransaction(async ({ abort }) => { + await model.save({ title: 'test-flag-off-abort' }); + await abort(); + }); + + const docs = await model.get({ title: 'test-flag-off-abort' }); + expect(docs).toHaveLength(1); + }); + }); }); describe('Entities elasticsearch index', () => { beforeEach(async () => { diff --git a/app/api/utils/withTransaction.ts b/app/api/utils/withTransaction.ts index 2f5d1e1b27..381b36094a 100644 --- a/app/api/utils/withTransaction.ts +++ b/app/api/utils/withTransaction.ts @@ -2,6 +2,7 @@ import { storage } from 'api/files/storage'; import { dbSessionContext } from 'api/odm/sessionsContext'; import { search } from 'api/search'; import { appContext } from './AppContext'; +import { tenants } from 'api/tenants'; interface TransactionOperation { abort: () => Promise; @@ -39,6 +40,9 @@ const performDelayedReindexes = async () => { const withTransaction = async ( operation: (context: TransactionOperation) => Promise ): Promise => { + if (!tenants.current().featureFlags?.v1_transactions) { + return operation({ abort: async () => {} }); + } const session = await dbSessionContext.startSession(); session.startTransaction(); let wasManuallyAborted = false;