public CompletionStage<Void> updateTransactionallyAsync(final Account account,
      final Collection<TransactWriteItem> additionalWriteItems) {

    return AsyncTimerUtil.record(UPDATE_TRANSACTIONALLY_TIMER, () -> {
      final List<TransactWriteItem> writeItems = new ArrayList<>(additionalWriteItems.size() + 1);
      writeItems.add(UpdateAccountSpec.forAccount(accountsTableName, account).transactItem());
      writeItems.addAll(additionalWriteItems);

      return asyncClient.transactWriteItems(TransactWriteItemsRequest.builder()
              .transactItems(writeItems)
              .build())
          .thenApply(response -> {
            account.setVersion(account.getVersion() + 1);
            return (Void) null;
          })
          .exceptionally(throwable -> {
            final Throwable unwrapped = ExceptionUtils.unwrap(throwable);

            if (unwrapped instanceof TransactionCanceledException transactionCanceledException) {
              if (CONDITIONAL_CHECK_FAILED.equals(transactionCanceledException.cancellationReasons().get(0).code())) {
                throw new ContestedOptimisticLockException();
              }

              if (transactionCanceledException.cancellationReasons()
                  .stream()
                  .anyMatch(reason -> TRANSACTION_CONFLICT.equals(reason.code()))) {

                throw new ContestedOptimisticLockException();
              }
            }

            throw CompletableFutureUtils.errorAsCompletionException(throwable);
          });
    });
  }
@Test
  void testUpdateTransactionallyWithMockTransactionConflictException() {
    final DynamoDbAsyncClient dynamoDbAsyncClient = mock(DynamoDbAsyncClient.class);

    accounts = new Accounts(mock(DynamoDbClient.class),
        dynamoDbAsyncClient,
        Tables.ACCOUNTS.tableName(),
        Tables.NUMBERS.tableName(),
        Tables.PNI_ASSIGNMENTS.tableName(),
        Tables.USERNAMES.tableName(),
        Tables.DELETED_ACCOUNTS.tableName());

    when(dynamoDbAsyncClient.transactWriteItems(any(TransactWriteItemsRequest.class)))
        .thenReturn(CompletableFuture.failedFuture(TransactionCanceledException.builder()
            .cancellationReasons(CancellationReason.builder()
                .code("TransactionConflict")
                .build())
            .build()));

    Account account = generateAccount("+14151112222", UUID.randomUUID(), UUID.randomUUID());

    assertThatThrownBy(() -> accounts.updateTransactionallyAsync(account, Collections.emptyList()).toCompletableFuture().join())
        .isInstanceOfAny(CompletionException.class)
        .hasCauseInstanceOf(ContestedOptimisticLockException.class);
  }