diff --git a/src/dataServices/dynamoDbBundleService.test.ts b/src/dataServices/dynamoDbBundleService.test.ts index 87bcd1e..c17d91e 100644 --- a/src/dataServices/dynamoDbBundleService.test.ts +++ b/src/dataServices/dynamoDbBundleService.test.ts @@ -8,7 +8,7 @@ import * as AWSMock from 'aws-sdk-mock'; import { QueryInput, TransactWriteItemsInput } from 'aws-sdk/clients/dynamodb'; import AWS from 'aws-sdk'; -import { BundleResponse, BatchReadWriteRequest } from 'fhir-works-on-aws-interface'; +import { BundleResponse, BatchReadWriteRequest, TypeOperation } from 'fhir-works-on-aws-interface'; import { DynamoDbBundleService } from './dynamoDbBundleService'; import { DynamoDBConverter } from './dynamoDb'; import { timeFromEpochInMsRegExp, utcTimeRegExp, uuidRegExp } from '../../testUtilities/regExpressions'; @@ -450,4 +450,55 @@ describe('atomicallyReadWriteResources', () => { await runUpdateTest(true); }); }); + + describe('Update as Create Cases', () => { + const runTest = async (supportUpdateCreate: boolean, operation: TypeOperation, isLockSuccessful: boolean) => { + // READ items (Failure) + AWSMock.mock('DynamoDB', 'query', (params: QueryInput, callback: Function) => { + callback(null, { Items: [] }); + }); + + const dynamoDb = new AWS.DynamoDB(); + const bundleService = new DynamoDbBundleService(dynamoDb, supportUpdateCreate); + + const batchRequest: BatchReadWriteRequest = { + operation, + resourceType: 'Patient', + id, + resource: `Patient/${id}`, + }; + // @ts-ignore + const actualResponse = await bundleService.lockItems([batchRequest]); + if (isLockSuccessful) { + expect(actualResponse).toStrictEqual({ + lockedItems: [], + successfulLock: true, + }); + } else { + expect(actualResponse).toStrictEqual({ + errorMessage: `Failed to find resources: Patient/${id}`, + errorType: 'USER_ERROR', + lockedItems: [], + successfulLock: false, + }); + } + }; + + const testCases = [ + // ['supportUpdateCreate', 'operation', 'isLockSuccessful'], + [true, 'create', true], + [true, 'update', true], + [true, 'read', false], + [false, 'create', true], + [false, 'update', false], + [false, 'read', false], + ]; + + // eslint-disable-next-line no-restricted-syntax + for (const [supportUpdateCreate, operation, isLockSuccessful] of testCases) { + test('lock update ', async () => { + await runTest(supportUpdateCreate as boolean, operation as TypeOperation, isLockSuccessful as boolean); + }); + } + }); }); diff --git a/src/dataServices/dynamoDbBundleService.ts b/src/dataServices/dynamoDbBundleService.ts index a7df78e..07d3121 100644 --- a/src/dataServices/dynamoDbBundleService.ts +++ b/src/dataServices/dynamoDbBundleService.ts @@ -31,6 +31,8 @@ export class DynamoDbBundleService implements Bundle { private readonly ELAPSED_TIME_WARNING_MESSAGE = 'Transaction time is greater than max allowed code execution time. Please reduce your bundle size by sending fewer Bundle entries.'; + readonly updateCreateSupported: boolean; + private dynamoDbHelper: DynamoDbHelper; private dynamoDb: DynamoDB; @@ -40,9 +42,10 @@ export class DynamoDbBundleService implements Bundle { private static readonly dynamoDbMaxBatchSize = 25; // Allow Mocking DDB - constructor(dynamoDb: DynamoDB, maxExecutionTimeMs?: number) { + constructor(dynamoDb: DynamoDB, supportUpdateCreate: boolean = false, maxExecutionTimeMs?: number) { this.dynamoDbHelper = new DynamoDbHelper(dynamoDb); this.dynamoDb = dynamoDb; + this.updateCreateSupported = supportUpdateCreate; this.maxExecutionTimeMs = maxExecutionTimeMs || 26 * 1000; } @@ -190,7 +193,11 @@ export class DynamoDbBundleService implements Bundle { const idItemsFailedToRead: string[] = []; for (let i = 0; i < itemResponses.length; i += 1) { const itemResponse = itemResponses[i]; - if (itemResponse instanceof ResourceNotFoundError) { + // allow for update as create scenario + if ( + itemResponse instanceof ResourceNotFoundError && + !(itemsToLock[i].operation === 'update' && this.updateCreateSupported) + ) { idItemsFailedToRead.push(`${itemsToLock[i].resourceType}/${itemsToLock[i].id}`); } } diff --git a/src/dataServices/dynamoDbDataService.ts b/src/dataServices/dynamoDbDataService.ts index f595da7..d8ec8f8 100644 --- a/src/dataServices/dynamoDbDataService.ts +++ b/src/dataServices/dynamoDbDataService.ts @@ -70,7 +70,7 @@ export class DynamoDbDataService implements Persistence, BulkDataAccess { constructor(dynamoDb: DynamoDB, supportUpdateCreate: boolean = false) { this.dynamoDbHelper = new DynamoDbHelper(dynamoDb); - this.transactionService = new DynamoDbBundleService(dynamoDb); + this.transactionService = new DynamoDbBundleService(dynamoDb, supportUpdateCreate); this.dynamoDb = dynamoDb; this.updateCreateSupported = supportUpdateCreate; }