async transaction()

in src/dataServices/dynamoDbBundleService.ts [102:209]


    async transaction(request: TransactionRequest): Promise<BundleResponse> {
        this.assertValidTenancyMode(request.tenantId);
        const { requests, startTime, tenantId } = request;
        if (requests.length === 0) {
            return {
                success: true,
                message: 'No requests to process',
                batchReadWriteResponses: [],
            };
        }

        // 1. Put a lock on all requests
        const lockItemsResponse = await this.lockItems(requests, tenantId);
        const { successfulLock } = lockItemsResponse;
        let { lockedItems } = lockItemsResponse;

        let elapsedTimeInMs = this.getElapsedTime(startTime);
        if (elapsedTimeInMs > this.maxExecutionTimeMs || !successfulLock) {
            await this.unlockItems(lockedItems, true);
            if (elapsedTimeInMs > this.maxExecutionTimeMs) {
                logger.warn(
                    'Locks were rolled back because elapsed time is longer than max code execution time. Elapsed time',
                    elapsedTimeInMs,
                );
                return {
                    success: false,
                    message: this.ELAPSED_TIME_WARNING_MESSAGE,
                    batchReadWriteResponses: [],
                    errorType: 'USER_ERROR',
                };
            }
            logger.error('Locks were rolled back because failed to lock resources');
            const { errorType, errorMessage } = lockItemsResponse;
            return {
                success: false,
                message: errorMessage || 'Failed to lock resources for transaction',
                batchReadWriteResponses: [],
                errorType,
            };
        }
        if (this.versionedLinks) {
            const wasSuccessful = await this.updatedReferences(requests, lockedItems, tenantId);
            elapsedTimeInMs = this.getElapsedTime(startTime);
            if (elapsedTimeInMs > this.maxExecutionTimeMs || !wasSuccessful) {
                await this.unlockItems(lockedItems, true, tenantId);
                if (elapsedTimeInMs > this.maxExecutionTimeMs) {
                    logger.warn(
                        'Locks were rolled back because elapsed time is longer than max code execution time. Elapsed time',
                        elapsedTimeInMs,
                    );
                    return {
                        success: false,
                        message: this.ELAPSED_TIME_WARNING_MESSAGE,
                        batchReadWriteResponses: [],
                        errorType: 'USER_ERROR',
                    };
                }
                logger.error('Locks were rolled back because failed to find versions of some resources');
                return {
                    success: false,
                    message: 'Failed to find some resource versions for transaction',
                    batchReadWriteResponses: [],
                    errorType: 'USER_ERROR',
                };
            }
        }

        // 2.  Stage resources
        const stageItemResponse = await this.stageItems(requests, lockedItems, tenantId);
        const { batchReadWriteResponses } = stageItemResponse;
        const successfullyStageItems = stageItemResponse.success;
        lockedItems = stageItemResponse.lockedItems;

        elapsedTimeInMs = this.getElapsedTime(startTime);
        if (elapsedTimeInMs > this.maxExecutionTimeMs || !successfullyStageItems) {
            lockedItems = await this.rollbackItems(batchReadWriteResponses, lockedItems, tenantId);
            await this.unlockItems(lockedItems, true, tenantId);

            if (elapsedTimeInMs > this.maxExecutionTimeMs) {
                logger.warn(
                    'Rolled changes back because elapsed time is longer than max code execution time. Elapsed time',
                    elapsedTimeInMs,
                );
                return {
                    success: false,
                    message: this.ELAPSED_TIME_WARNING_MESSAGE,
                    batchReadWriteResponses: [],
                    errorType: 'USER_ERROR',
                };
            }
            logger.error('Rolled changes back because staging of items failed');
            return {
                success: false,
                message: 'Failed to stage resources for transaction',
                batchReadWriteResponses: [],
                errorType: 'SYSTEM_ERROR',
            };
        }

        // 3. unlockItems
        await this.unlockItems(lockedItems, false, tenantId);

        return {
            success: true,
            message: 'Successfully committed requests to DB',
            batchReadWriteResponses,
        };
    }