ダメ元エンジニアのお勉強おメモ

ほとんど自分用のメモです。AWS をよく触ります。Web アプリとか作ります。Raspberry Pi も好きです。

DynamoDB で存在しないデータに対して delete-item した際にエラーを発生させたい

概要

DynamoDB で delete-item した際、削除対象のデータが存在しなかったとしてもエラーは発生しない。AWS CLI がその挙動なので、恐らくどの言語でも同じだと思う。

% aws dynamodb delete-item \
  --table-name sample-table \ 
  --key '{"pk": {"S": "sample-id"}, "sk": {"N": "1"}}'

じゃあ逆にエラーを発生させたい場合はどうするの?って思って調べてみたので下記に書いていく。ちなみに言語は TypeScript で。

通常の挙動

↑で書いた AWS CLI 版 delete-item を TypeScript で書くとこんな感じ。削除対象のデータが存在しなくてもエラーは出ない。

import * as DynamoDB from 'aws-sdk/clients/dynamodb';

const DYNAMODB_API_VERSION = '2012-10-08';
const REGION = 'ap-northeast-1';
const TABLE_NAME = 'sample-table';

const dynamodbDocumentClient = new DynamoDB.DocumentClient({
  apiVersion: DYNAMODB_API_VERSION,
  region: REGION,
});

(async () => {
  const params: DynamoDB.DocumentClient.DeleteItemInput = {
    TableName: TABLE_NAME,
    Key: {
      pk: 'sample-id',
      sk: 1,
    },
  };
  await dynamodbDocumentClient.delete(params).promise();
})();

エラーを発生させる版

ConditionExpression で PK、SK に該当するデータが存在するか確認すれば OK。

import * as DynamoDB from 'aws-sdk/clients/dynamodb';

const DYNAMODB_API_VERSION = '2012-10-08';
const REGION = 'ap-northeast-1';
const TABLE_NAME = 'sample-table';

const dynamodbDocumentClient = new DynamoDB.DocumentClient({
  apiVersion: DYNAMODB_API_VERSION,
  region: REGION,
});

(async () => {
  const params: DynamoDB.DocumentClient.DeleteItemInput = {
    TableName: TABLE_NAME,
    Key: {
      pk: 'sample-id',
      sk: 1,
    },
    ExpressionAttributeNames: {
      '#pk': 'pk',
      '#sk': 'sk',
    },
    ConditionExpression: 'attribute_exists(#pk) and attribute_exists(#sk)',
  };

  try {
    await dynamodbDocumentClient.delete(params).promise();
  } catch (e) {
    if (e.code === 'ConditionalCheckFailedException') {
      console.log('削除する対象のデータが存在しなかったよ');
    } else {
      console.log('それ以外のエラーだよ');
    }
  }
})();

おまけ

try / catch で得たエラーの型がデフォルトで any になる記憶だったのだが、unknown になっていた。

調べてみると下記の記事でこんな記述があった。

TypeScript 4.4 から導入予定の useUnknownInCatchVariables 設定を使えば型アノテーションなしで catch した値を unknown として扱うことができます TypeScript のエラーハンドリングを考える - Qiita

tsconfig.json の useUnknownInCatchVariables を false にすると、今までの挙動に戻った。へえ〜。