ããã¯ããªã«ãããããŠæžãããã®ïŒ
ä»åã¯ãAmazon DynamoDBã®ãã©ã³ã¶ã¯ã·ã§ã³ãè©ŠããŠã¿ããããªãšæããŸãã
DynamoDB トランザクションで複雑なワークフローを管理する - Amazon DynamoDB
Amazon DynamoDBã®ãã©ã³ã¶ã¯ã·ã§ã³
Amazon DynamoDBã«ã¯ãã©ã³ã¶ã¯ã·ã§ã³ãããããã§ãã
DynamoDB トランザクションで複雑なワークフローを管理する - Amazon DynamoDB
ACIDãå®çŸãããããšèšã£ãŠããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã«ãã£ãŠ DynamoDB ã«äžå¯åæ§ãäžè²«æ§ãåé¢æ§ãèä¹ æ§ (ACID) ãå®çŸããããããã¢ããªã±ãŒã·ã§ã³å ã§ã®ããŒã¿ã®ç²ŸåºŠãç¶æããããšãã§ããŸãã
ãšã¯ãã£ãŠããRDBMSã§ãããã©ã³ã¶ã¯ã·ã§ã³ãšã¯å·®ã¯ããã§ãããã
ãã©ã³ã¶ã¯ã·ã§ã³ã«ã¯TransactWriteItems
ãšTransactGetItems
ã®2çš®é¡ã®æäœããããæžã蟌ã¿ããã³èªã¿èŸŒã¿ã§ã°ã«ãŒãå
ã§ããããã§ãã
ãã©ã³ã¶ã¯ã·ã§ã³æžã蟌㿠API ã䜿çšããŠãè€æ°ã® PutãUpdateãDeleteãConditionCheck ã®åã¢ã¯ã·ã§ã³ãã°ã«ãŒãåã§ããŸãããã®åŸãã¢ã¯ã·ã§ã³ãåäžã® TransactWriteItems ãªãã¬ãŒã·ã§ã³ãšããŠéä¿¡ã§ããŸãããã®ãªãã¬ãŒã·ã§ã³ã¯ãŠããããšããŠæåãŸãã¯å€±æããŸããåãããšãè€æ°ã® Get ã¢ã¯ã·ã§ã³ã«ãåœãŠã¯ãŸããŸãããã®å Žåã1 ã€ã® TransactGetItems ãªãã¬ãŒã·ã§ã³ãšããŠã°ã«ãŒãåããéä¿¡ã§ããŸãã
ãã£ãšè©³ããå 容ã¯ããã¡ãã®ããŒãžã«èšèŒããããŸãã
Amazon DynamoDB Transactions: 仕組み - Amazon DynamoDB
ãŸãã¯ãTransactWriteItems APIããã
Amazon DynamoDB Transactions: ä»çµã¿ / TransactWriteItems API
TransactWriteItems
ã¯ãæ倧25åã®æžã蟌ã¿æäœããŸãšããŠè¡ãAPIã®ããã§ãã
TransactWriteItems ã¯ãæ倧 25 ã®æžã蟌ã¿ã¢ã¯ã·ã§ã³ã 1 ã€ã®ãªãŒã«ãªã¢ããã·ã³ã°ãªãã¬ãŒã·ã§ã³ã«ã°ã«ãŒãåãããåæçã§ã¹ãçãªæžã蟌ã¿ãªãã¬ãŒã·ã§ã³ã§ãããããã®ã¢ã¯ã·ã§ã³ã¯ãåã AWS ã¢ã«ãŠã³ãããã³åããªãŒãžã§ã³å ã® 1 ã€ä»¥äžã® DynamoDB ããŒãã«ã«ããæ倧 25 åã®ç°ãªãé ç®ãã¿ãŒã²ããã§ããŸãããã©ã³ã¶ã¯ã·ã§ã³å ã®ã¢ã€ãã ã®åèšãµã€ãºã¯ 4 MB ãè¶ ããããšã¯ã§ããŸããããã¹ãŠæåãããã©ããæåããªããã®ã©ã¡ããšãªãããã«ãã¢ãããã¯ã«å®è¡ãããŸãã
åäžAWSã¢ã«ãŠã³ããåäžãªãŒãžã§ã³ã®å¶éããŸãšããŠå®è¡ããæã®ããŒã¿éã«ãå¶éãããããã§ãã
ããæžããšãããåŠçã®ãããªã€ã¡ãŒãžãåããŸãããåŠçãã¢ãããã¯ã«è¡ãããããšããããåŠçãšã®å·®ç°ã®ããã§ãã
TransactWriteItems ãªãã¬ãŒã·ã§ã³ã¯ãå«ãŸãããã¹ãŠã®ã¢ã¯ã·ã§ã³ãæ£åžžã«å®äºããå¿ èŠããããããã§ãªãå Žåã¯å€æŽããŸã£ããè¡ãããªããšããç¹ã§ BatchWriteItem ãªãã¬ãŒã·ã§ã³ãšã¯ç°ãªããŸããBatchWriteItem ãªãã¬ãŒã·ã§ã³ã§ã¯ããããå ã®äžéšã®ã¢ã¯ã·ã§ã³ã®ã¿æåããä»ã®ã¢ã¯ã·ã§ã³ã¯æåããªãããšãããåŸãŸãã
ããããããããåŠççšã®APIã¯å¥ã«ãããŸãããâŠã
TransactWriteItems
ãã©ã³ã¶ã¯ã·ã§ã³ã«å«ããæäœã®äžã«ãåãã¢ã€ãã ãåŠçããæäœãè€æ°å«ãããšã¯ã§ããŸããã
åããã©ã³ã¶ã¯ã·ã§ã³å ã®è€æ°ã®ãªãã¬ãŒã·ã§ã³ãåãé ç®ãã¿ãŒã²ãããšããããšã¯ã§ããŸãããããšãã°ãåããã©ã³ã¶ã¯ã·ã§ã³å ã§åãé ç®ã«å¯Ÿã㊠ConditionCheck ãå®è¡ããUpdate ã¢ã¯ã·ã§ã³ãå®è¡ããããšã¯ã§ããŸããã
TransactWriteItems
ã«å«ããããšãã§ããæäœã¯ã以äžã®4ã€ã§ãã
- Put
- Update
- Delete
- ConditionCheck
ConditionCheckãšããæäœãèŠæ
£ããªãã£ãã®ã§ãããããã¯TransactWriteItems
ã§äœ¿ããæäœã®ããã§ããã
TransactWriteItems
ã«ã€ããŠã¯ããã¯ã©ã€ã¢ã³ãããŒã¯ã³ããšãããã®ããªã¯ãšã¹ãã«å«ããããšã§ãã¹ãçã§ããããšã
確èªã§ããŸãã
TransactWriteItems åŒã³åºããè¡ã£ãŠãªã¯ãšã¹ããã¹ãçã§ããããšã確èªãããšãããªãã·ã§ã³ã§ã¯ã©ã€ã¢ã³ãããŒã¯ã³ãå«ããããšãã§ããŸãããã©ã³ã¶ã¯ã·ã§ã³ãã¹ãçã«ãããšãæ¥ç¶ã®ã¿ã€ã ã¢ãŠããä»ã®æ¥ç¶ã®åé¡ã®ããã«åããªãã¬ãŒã·ã§ã³ãè€æ°åéä¿¡ãããå Žåã«ãã¢ããªã±ãŒã·ã§ã³ãšã©ãŒãé²ãããšãã§ããŸãã
å ã® TransactWriteItems åŒã³åºããæåããå Žåãåãã¯ã©ã€ã¢ã³ãããŒã¯ã³ã䜿çšãããã®åŸã® TransactWriteItems åŒã³åºããå€æŽãå ããã«æ£åžžã«çµæãè¿ããŸãã
ã¯ã©ã€ã¢ã³ãããŒã¯ã³ã¯äœ¿çšãããªã¯ãšã¹ããã10åéæå¹ã§ã10åçµéãããšæ°ãããªã¯ãšã¹ããšããŠæ±ãããŸãã
ãŸãã10å以å
ã«åãã¯ã©ã€ã¢ã³ãããŒã¯ã³ã䜿ã£ãŠãªã¯ãšã¹ããç¹°ãè¿ãå Žåã«ãå«ãŸãããªã¯ãšã¹ãã®å
容ãå€æŽãããš
Amazon DynamoDBããIdempotentParameterMismatch
ãšã©ãŒãã¹ããŒãããŸãã
TransactWriteItems
ã倱æããæ¡ä»¶ã¯ããã€ãããããã§ããã以äžãããã¯æ³šæã§ããããã
- ãã
TransactWriteItems
ãªã¯ãšã¹ãå ã®1ã€ä»¥äžã®ã¢ã€ãã ã«å¯ŸããåŠçããä»ã«ç¶ç¶äžã®TransactWriteItems
ãªãã¬ãŒã·ã§ã³ãšç«¶åãã- ãã®å Žåã
TransactionCanceledException
ãšã©ãŒãã¹ããŒããã
- ãã®å Žåã
- ãã©ã³ã¶ã¯ã·ã§ã³ãå®äºããããããžã§ã³ããã£ãã·ãã£ãŒã足ããªã
- é ç®ãµã€ãºã倧ãããªãããã (400 KB è¶ )ãããŒã«ã«ã»ã«ã³ããªã€ã³ããã¯ã¹ (LSI) ã倧ãããªããããããŸãã¯ãã©ã³ã¶ã¯ã·ã§ã³ã«ããå€æŽãå ããããããã«ãã®æ¡ä»¶ãæºãããŠããŸãå Žå
ãã©ã³ã¶ã¯ã·ã§ã³ã®ç«¶åã«ã€ããŠã¯ã詳ããã¯ä»¥äžã«æžããŠãããŸãã
Amazon DynamoDB Transactions: ä»çµã¿ / DynamoDB ã§ã®ãã©ã³ã¶ã¯ã·ã§ã³ç«¶åã®åŠç
PutItem
ãUpdateItem
ãDeleteItem
ããã©ã³ã¶ã¯ã·ã§ã³ãšç«¶åããŠæåŠãããå Žåã¯ãTransactionConflictException
ã
ã¹ããŒãããããã§ãã
次ã¯ãTransactGetItems APIã«ã€ããŠã
Amazon DynamoDB Transactions: ä»çµã¿ / TransactGetItems API
TransactGetItems
ã¯ãTransactWriteItems
ã®èªã¿èŸŒã¿æäœçãšããæãã§ããã
TransactGetItems ã¯ãæ倧 25 åã® Get ã¢ã¯ã·ã§ã³ããŸãšããŠã°ã«ãŒãåããåæèªã¿åããªãã¬ãŒã·ã§ã³ã§ãããããã®ã¢ã¯ã·ã§ã³ã¯ãåã AWS ã¢ã«ãŠã³ãããã³ãªãŒãžã§ã³å ã® 1 ã€ä»¥äžã® DynamoDB ããŒãã«ã«ããæ倧 25 åã®ç°ãªãé ç®ãã¿ãŒã²ããã«ããããšãã§ããŸãããã©ã³ã¶ã¯ã·ã§ã³å ã®é ç®ã®åèšãµã€ãºã¯ 4 MB ãè¶ ããããšã¯ã§ããŸããã
Amazon DynamoDBã¯ãã©ã³ã¶ã¯ã·ã§ã³ãšããŠãReadãšWriteã¯å®å šã«åé¢ãããããã§ããã
ãŸããRDBMSã®ãã©ã³ã¶ã¯ã·ã§ã³ã®ã€ã¡ãŒãžãããããããåŠçã«è¿ãå°è±¡ããã¯ãæã£ãŠããŸãã®ã§ããã
TransactGetItems
ã«å«ããããšãã§ããæäœã¯ãGetã®ã¿ã§ãã
TransactGetItems
ã¯ãæäœå¯Ÿè±¡ã®ã¢ã€ãã ã«å¯ŸããåŠçãå®è¡äžã®TransactWriteItems
ã«å«ãŸããæäœãšç«¶åããå Žåã
TransactionCanceledException
ã§å€±æããããã§ãã
TransactGetItems ãªã¯ãšã¹ãããTransactWriteItems ãªã¯ãšã¹ãå ã® 1 ã€ä»¥äžã®é ç®ã«å¯Ÿããç¶ç¶äžã® TransactGetItems ãªãã¬ãŒã·ã§ã³ãšç«¶åããå Žåããã®å Žåããªã¯ãšã¹ã㯠TransactionCanceledException ã§å€±æããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã®åé¢ã¬ãã«ã
Amazon DynamoDB Transactions: ä»çµã¿ / DynamoDB ãã©ã³ã¶ã¯ã·ã§ã³ã®åé¢ã¬ãã«
TransactWriteItems
ããã³TransactGetItems
ã®ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ã¯ãSerializableã®ããã§ãã
ãªã®ã§ããã©ã³ã¶ã¯ã·ã§ã³ã¯è€æ°åæã«ã¯å®è¡ã§ããªãããšã«ãªããŸãã
çŽååå¯èœåé¢ã¬ãã«ã§ã¯ãè€æ°ã®åæãªãã¬ãŒã·ã§ã³ã®çµæã¯ãåã®ãªãã¬ãŒã·ã§ã³ãå®äºãããŸã§ãªãã¬ãŒã·ã§ã³ãéå§ãããªãå Žåãšåãã«ãªããŸãã
ããã¯å¯Ÿè±¡ã¯æèšãããŠããŸããããããã¥ã¡ã³ãå ã®äŸãèŠãŠãããšã¢ã€ãã åäœããšããããšã«ãªãã®ã§ããããïŒ
Amazon DynamoDBã®åçš®æäœãšãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ã®ãããã³ã°ã¯ã以äžã«ãªãããã§ãã
æäœ | ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã« |
---|---|
DeleteItem | Serializable |
PutItem | Serializable |
UpdateItem | Serializable |
GetItem | Serializable |
BatchGetItem | Read Committed |
BatchWriteItem | NOT Serializable |
Query | Read Committed |
Scan | Read Committed |
ãã®ä» | Serializable |
BatchWriteItemãããããããªããªïŒãšæã£ãã®ã§ããã説æãèŠããšBatchWriteItemã«å«ãŸããåã
ã®ã¢ã€ãã ã«å¯Ÿããæäœã¯
Serializableã ããã©ããBatchWriteItemå
šäœã¯Serializableã§ã¯ãªãããšããããšã¿ããã§ãã
ãã©ã³ã¶ã¯ã·ã§ã³ãªãã¬ãŒã·ã§ã³éãš BatchWriteItem ãªãã¬ãŒã·ã§ã³å ã®åã ã®æšæºæžã蟌ã¿éã«ã¯çŽååå¯èœåé¢ããããŸããããã©ã³ã¶ã¯ã·ã§ã³ãšãŠããããšããŠã® BatchWriteItem ãªãã¬ãŒã·ã§ã³ã®éã«ã¯çŽååå¯èœåé¢ã¯ãããŸããã
BatchGetItemãRead Committedãªã®ã䌌ãçç±ã§ããã
Read Committedã®èª¬æã¯ããã®ããã«ãªã£ãŠããŸãã
ã³ãããæžã¿èªã¿åãåé¢ã§ã¯ãèªã¿åããªãã¬ãŒã·ã§ã³ãåžžã«é ç®ã®ã³ãããæžã¿å€ãè¿ããŸããã³ãããæžã¿èªã¿åãåé¢ã§ã¯ãèªã¿åããªãã¬ãŒã·ã§ã³ã®çŽåŸã«é ç®ã®å€æŽãé²æ¢ãããŸããã
ãã©ã³ã¶ã¯ã·ã§ã³ã®ãã¹ããã©ã¯ãã£ã¹ã¯ããã¡ãã
Amazon DynamoDB Transactions: ä»çµã¿ / ãã©ã³ã¶ã¯ã·ã§ã³ã®ãã¹ããã©ã¯ãã£ã¹
ãã®ãããããã€ã³ãã¿ããã§ããã
- ããŒãã«ã§èªåã¹ã±ãŒãªã³ã°ãæå¹ã«ããããèªã¿èŸŒã¿ãæžã蟌ã¿ã®ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããã®ã«ååãªã¹ã«ãŒããã容éãããããžã§ãã³ã°ãè¡ã
TransactWriteItems
åŒã³åºãæã«ClientRequestToken
å±æ§ãå«ãããªã¯ãšã¹ããã¹ãçãšãªãããã«ãã- ãã©ã³ã¶ã¯ã·ã§ã³ã«ãŸãšããæäœã¯ãæäœéã«ããããš
- ãã©ã³ã¶ã¯ã·ã§ã³ã«ãŸãšããããšããŠããæäœã«ã¢ãããã¯ã§ããå¿ èŠããªããã®ãããã°ããã©ã³ã¶ã¯ã·ã§ã³ãåå²ããæ¹ããã
- ãã®æ¹ãã¹ã«ãŒããããåäžãããã©ã³ã¶ã¯ã·ã§ã³èªäœãæåããå¯èœæ§ãé«ããªã
- åãã¢ã€ãã ãåæã«æŽæ°ãããã©ã³ã¶ã¯ã·ã§ã³ãå€æ°çºçããªãããã«ããããš
- ãã£ã³ã»ã«ã®åå ãšãªã
- å±æ§ã®ã»ãããè€æ°ã®ã¢ã€ãã ã«åæ£ããŠãããããããã©ã³ã¶ã¯ã·ã§ã³ã§ã²ãšãŸãšãã«æŽæ°ããããããªå Žåãå±æ§ãã²ãšã€ã®ã¢ã€ãã ã«ãŸãšããã©ã³ã¶ã¯ã·ã§ã³ãã·ã³ãã«ã«ããæ¹ããã
- ããŒã¿ã倧éã«åãçµãããã«ãã©ã³ã¶ã¯ã·ã§ã³ã䜿çšããªãããš
- ãã®çšéã«ã¯
BatchWriteItem
ã䜿çšããããš
- ãã®çšéã«ã¯
説æã¯ãããããã«ããŠãå®éã«äœ¿ã£ãŠãããŸãããã
確èªã«ã¯ãAmazon DynamoDBã®ããŒã«ã«çã䜿ããŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ aws --version aws-cli/2.4.20 Python/3.8.8 Linux/5.4.0-100-generic exe/x86_64.ubuntu.20 prompt/off $ java --version openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment (build 17.0.1+12-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.1+12-Ubuntu-120.04, mixed mode, sharing)
ããŒã«ã«çã®Amazon DynamoDBïŒDynamoDB Local ïŒã®æ å ±ã
$ grep -A 2 'Release Notes' README.txt Release Notes ----------------------------- 2022-1-10 (1.18.0)
ã€ã³ã¡ã¢ãªãŒã§èµ·åãããŠãããŸãã
$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -inMemory
ããŒã«ã«çã®Amazon DynamoDBã«ãAWS CLIã§ã¢ã¯ã»ã¹ããããã®ã¯ã¬ãã³ã·ã£ã«ã
$ export AWS_ACCESS_KEY_ID=fakeMyKeyId $ export AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey $ export AWS_DEFAULT_REGION=ap-northeast-1
確èªã¯ãAWS SDK for JavaScriptã䜿ã£ãŠãNode.jsã§è¡ããŸãã
$ node --version v16.14.0 $ npm --version 8.3.1
æºå
Node.jsãããžã§ã¯ããäœæããŸãããã¹ãã³ãŒãã§ç¢ºèªããããšã«ããŸãã
$ npm init -y $ npm i -D typescript $ npm i -D -E prettier $ npm i -D jest @types/jest $ npm i -D esbuild esbuild-jest $ mkdir src test
Node.jsã®å宣èšãšAWS SDK for JavaScript v2ãã€ã³ã¹ããŒã«ã
$ npm i -D @types/node@v16 $ npm i aws-sdk
äŸåé¢ä¿ã¯ããã®ããã«ãªããŸããã
"devDependencies": { "@types/jest": "^27.4.0", "@types/node": "^16.11.25", "esbuild": "^0.14.23", "esbuild-jest": "^0.5.0", "jest": "^27.5.1", "prettier": "2.5.1", "typescript": "^4.5.5" }, "dependencies": { "aws-sdk": "^2.1079.0" }
èšå®ã¯ãã¡ãã
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
tsconfig.typecheck.conf
{ "extends": "./tsconfig", "compilerOptions": { "baseUrl": "./", "noEmit": true }, "include": [ "src", "test" ] }
.prettierrc.json
{ "singleQuote": true }
jest.config.js
module.exports = { testEnvironment: 'node', transform: { "^.+\\.tsx?$": "esbuild-jest" } };
ä»åã¯ãããã¥ã¡ã³ãã€ã³ã¿ãŒãã§ãŒã¹ã䜿ã£ãŠããããšã«ããŸãã
ドキュメントインターフェイス - Amazon DynamoDB
APIã¯ãã¡ãã
Class: AWS.DynamoDB.DocumentClient — AWS SDK for JavaScript
䜿ãããŒãã«ã§ããã2ã€ããŒãã«ãäœæããããšã«ããŸããã
$ aws dynamodb create-table \ --endpoint-url http://localhost:8000 \ --table-name People \ --attribute-definitions \ AttributeName=familyId,AttributeType=N \ AttributeName=firstName,AttributeType=S \ --key-schema \ AttributeName=familyId,KeyType=HASH \ AttributeName=firstName,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=10,WriteCapacityUnits=5 \ --table-class STANDARD $ aws dynamodb create-table \ --endpoint-url http://localhost:8000 \ --table-name Books \ --attribute-definitions \ AttributeName=isbn,AttributeType=S \ --key-schema \ AttributeName=isbn,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=10,WriteCapacityUnits=5 \ --table-class STANDARD
人ãšæžç±ã§ããã
ããŒã¿ã¯ãããªæãã§ã
People
ããŒãã«ã¯ãµã¶ãšããããã®äžã®familyId
ãããŒãã£ã·ã§ã³ããŒã«ãfirstName
ããœãŒãããŒã«ããŠããŸãã
ããŒã¿ã¯å
šéšã§14件ãããŸãã
test/people.json
[ { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ãµã¶ãš", "age": 24 }, { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ãã¹ãª", "age": 28 }, { "familyId": 1, "lastName": "磯é", "firstName": "波平", "age": 54 }, { "familyId": 1, "lastName": "磯é", "firstName": "ãã", "age": 50 }, { "familyId": 1, "lastName": "磯é", "firstName": "ã«ããª", "age": 11 }, { "familyId": 1, "lastName": "磯é", "firstName": "ã¯ã«ã¡", "age": 9 }, { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ã¿ã©ãª", "age": 3 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ããªã¹ã±", "age": 26 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ã¿ã€ã³", "age": 22 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ã€ã¯ã©", "age": 1 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "é£ç©", "age": 60 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "ã軜", "age": 50 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "çå ", "age": 20 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "æµ®æ±", "age": 16 } ]
次ã¯ãæžç±ãããã·ã¥ããŒã¯isbn
ã§ãããŒã¿ã¯å
šéšã§12件ã§ãã
test/books.json
[ { "isbn": "978-4815607654", "title": "AWSã³ã³ããèšèšã»æ§ç¯[æ¬æ Œ]å ¥é", "price": 3300, "publicationDate": "2021-10-21" }, { "isbn": "978-4295006657", "title": "Amazon Web Servicesã€ã³ãã©ãµãŒãã¹æŽ»çšå€§å š ã·ã¹ãã æ§ç¯/èªååãããŒã¿ã¹ãã¢ãé«ä¿¡é Œå (impress top gear)", "price": 5060, "publicationDate": "2019-09-05" }, { "isbn": "978-4797392579", "title": "Amazon Web Services ãã¿ãŒã³å¥æ§ç¯ã»éçšã¬ã€ã æ¹èšç¬¬2ç", "price": 3740, "publicationDate": "2018-03-23" }, { "isbn": "978-4797392562", "title": "Amazon Web Services æ¥åã·ã¹ãã èšèšã»ç§»è¡ã¬ã€ã", "price": 3520, "publicationDate": "2018-01-20" }, { "isbn": "978-4774176734", "title": "Amazon Web Serviceså®è·µå ¥é (WEB+DB PRESS plus)", "price": 2838, "publicationDate": "2015-11-10" }, { "isbn": "978-4822277376", "title": "Amazon Web Services ã¯ã©ãŠããã¶ã€ã³ãã¿ãŒã³èšèšã¬ã€ããæ¹èšç", "price": 2970, "publicationDate": "2015-05-28" }, { "isbn": "978-4822277369", "title": "Amazon Web Services ã¯ã©ãŠããã¶ã€ã³ãã¿ãŒã³å®è£ ã¬ã€ããæ¹èšç", "price": 4180, "publicationDate": "2015-03-09" }, { "isbn": "978-4822292508", "title": "Amazon Web Services å®çªæ¥åã·ã¹ãã 14ãã¿ãŒã³ èšèšã¬ã€ã", "price": 2750, "publicationDate": "2018-09-28" }, { "isbn": "978-4863543140", "title": "åºç€ããåŠã¶ ãµãŒããŒã¬ã¹éçº", "price": 3058, "publicationDate": "2020-07-22" }, { "isbn": "978-4839964566", "title": "Amazon Web Servicesã䜿ã£ããµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³éçºã¬ã€ã", "price": 3300, "publicationDate": "2018-03-16" }, { "isbn": "978-4297113292", "title": "ã¿ããªã®AWS ãAWSã®åºæ¬ãææ°ã¢ãŒããã¯ãã£ã§ãŸãããšç解!", "price": 2618, "publicationDate": "2020-04-17" }, { "isbn": "978-4798144696", "title": "Amazon Web Servicesã§ã¯ãããæ°ç±³ããã°ã©ãã®ããã®ã¯ã©ãŠãè¶ å ¥é", "price": 3278, "publicationDate": "2016-06-16" } ]
ã€ãŸãããã¹ãããŒã¿ã¯èš26件ãããŸãããã©ã³ã¶ã¯ã·ã§ã³ã§æ±ãããªã¯ãšã¹ãã®åæ°ã®äžéã¯25åãªã®ã§ããã®ç¢ºèªã«ã䜿ããããš
æããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã䜿ã£ãŠã¿ã
ã§ã¯ããã©ã³ã¶ã¯ã·ã§ã³ã䜿ãããã°ã©ã ãäœæããŸãã
ããŒã¿ã«ãããã³ã°ããã¯ã©ã¹ãäœæã
src/person.ts
export class Person { familyId: number; lastName: string; firstName: string; age: number; constructor( familyId: number, lastName: string, firstName: string, age: number ) { this.familyId = familyId; this.lastName = lastName; this.firstName = firstName; this.age = age; } }
src/book.ts
export class Book { isbn: string; title: string; price: number; publicationDate: string; constructor( isbn: string, title: string, price: number, publicationDate: string ) { this.isbn = isbn; this.title = title; this.price = price; this.publicationDate = publicationDate; } }
ãã¹ãã³ãŒãã®import
éšåãšãDocumentClient
ã®äœæã
test/transaction.test.ts
import { DocumentClient } from 'aws-sdk/clients/dynamodb'; import fs from 'fs'; import { Book } from '../src/book'; import { Person } from '../src/person'; const dynamodb = new DocumentClient({ credentials: { accessKeyId: 'fakeMyKeyId', secretAccessKey: 'fakeSecretAccessKey', }, region: 'ap-northeast-1', endpoint: 'http://localhost:8000', }); // ããã«ããã¹ããæžãïŒ
ãŸãã¯ããã©ã³ã¶ã¯ã·ã§ã³ã䜿ã£ãŠæžã蟌ã¿ãè¡ã£ãŠã¿ãŸãã
䜿ãã®ã¯ãDocumentClient#transactWrite
ã¡ãœããã§ãã
Class: AWS.DynamoDB.DocumentClient / transactWrite
test('write transaction getting started', async () => { const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ) as Person[]; const katsuo = people[4]; const wakame = people[5]; const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ); const book1 = books[0]; const book2 = books[1]; const params: DocumentClient.TransactWriteItemsInput = { TransactItems: [ { Put: { TableName: 'People', Item: katsuo, }, }, { Put: { TableName: 'People', Item: wakame, }, }, { Put: { TableName: 'Books', Item: book1, }, }, { Put: { TableName: 'Books', Item: book2, }, }, ], }; const result = await dynamodb.transactWrite(params).promise(); expect(result).not.toBeNull(); expect(result).toEqual({}); });
æåã«åããŒãã«çšã«ããŒã¿ã2ã¢ã€ãã ãã€åã£ãŠããŠ
const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ) as Person[]; const katsuo = people[4]; const wakame = people[5]; const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ); const book1 = books[0]; const book2 = books[1];
ããããã©ã³ã¶ã¯ã·ã§ã³ã®Putçšã®ãªã¯ãšã¹ããšããŠãŸãšããŸãã
const params: DocumentClient.TransactWriteItemsInput = { TransactItems: [ { Put: { TableName: 'People', Item: katsuo, }, }, { Put: { TableName: 'People', Item: wakame, }, }, { Put: { TableName: 'Books', Item: book1, }, }, { Put: { TableName: 'Books', Item: book2, }, }, ], };
ããšã¯DocumentClient#transactWrite
ã¡ãœããã§æžã蟌ãã§çµäºã§ãã
const result = await dynamodb.transactWrite(params).promise(); expect(result).not.toBeNull(); expect(result).toEqual({});
Put
以å€ã«æå®ã§ããã®ã¯ãUPdate
ãDelete
ãConditionCheck
ã§ãã
次ã¯ããã£ãä»æžã蟌ãã ããŒã¿ã«å¯ŸããŠããã©ã³ã¶ã¯ã·ã§ã³ã䜿ã£ãŠèªã¿èŸŒã¿ãè¡ã£ãŠã¿ãŸãããã
䜿ãã®ã¯DocumentClient#transactGet
ã¡ãœããã§ãã
Class: AWS.DynamoDB.DocumentClient / transactGet
test('read transaction, getting started', async () => { const params: DocumentClient.TransactGetItemsInput = { TransactItems: [ { Get: { TableName: 'People', Key: { familyId: 1, firstName: 'ã«ããª', }, }, }, { Get: { TableName: 'People', Key: { familyId: 1, firstName: 'ã¯ã«ã¡', }, }, }, { Get: { TableName: 'Books', Key: { isbn: '978-4815607654', }, }, }, { Get: { TableName: 'Books', Key: { isbn: '978-4295006657', }, }, }, ], }; const result = await dynamodb.transactGet(params).promise(); if (result.Responses) { const responses = result.Responses; const katsuo = responses[0].Item as Person; expect(katsuo.familyId).toBe(1); expect(katsuo.lastName).toBe('磯é'); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); const wakame = responses[1].Item as Person; expect(wakame.familyId).toBe(1); expect(wakame.lastName).toBe('磯é'); expect(wakame.firstName).toBe('ã¯ã«ã¡'); expect(wakame.age).toBe(9); const awsContainerBook = responses[2].Item as Book; expect(awsContainerBook.isbn).toBe('978-4815607654'); expect(awsContainerBook.title).toBe('AWSã³ã³ããèšèšã»æ§ç¯[æ¬æ Œ]å ¥é'); expect(awsContainerBook.price).toBe(3300); expect(awsContainerBook.publicationDate).toBe('2021-10-21'); const awsInfraBook = responses[3].Item as Book; expect(awsInfraBook.isbn).toBe('978-4295006657'); expect(awsInfraBook.title).toBe( 'Amazon Web Servicesã€ã³ãã©ãµãŒãã¹æŽ»çšå€§å š ã·ã¹ãã æ§ç¯/èªååãããŒã¿ã¹ãã¢ãé«ä¿¡é Œå (impress top gear)' ); expect(awsInfraBook.price).toBe(5060); expect(awsInfraBook.publicationDate).toBe('2019-09-05'); } else { throw new Error('test failed'); } });
Getçšã®ãªã¯ãšã¹ãããŸãšããŠ
const params: DocumentClient.TransactGetItemsInput = { TransactItems: [ { Get: { TableName: 'People', Key: { familyId: 1, firstName: 'ã«ããª', }, }, }, { Get: { TableName: 'People', Key: { familyId: 1, firstName: 'ã¯ã«ã¡', }, }, }, { Get: { TableName: 'Books', Key: { isbn: '978-4815607654', }, }, }, { Get: { TableName: 'Books', Key: { isbn: '978-4295006657', }, }, }, ], };
DocumentClient#transactGet
ã¡ãœããã§å®è¡ããŸãã
const result = await dynamodb.transactGet(params).promise();
çµæã¯ãResponses
ã«é
åãšããŠå
¥ã£ãŠããŸããå®éã®å€ã¯Item
ãšããèŠçŽ ã«ãããã³ã°ãããŠããŸããã
if (result.Responses) { const responses = result.Responses; const katsuo = responses[0].Item as Person; expect(katsuo.familyId).toBe(1); expect(katsuo.lastName).toBe('磯é'); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); const wakame = responses[1].Item as Person; expect(wakame.familyId).toBe(1); expect(wakame.lastName).toBe('磯é'); expect(wakame.firstName).toBe('ã¯ã«ã¡'); expect(wakame.age).toBe(9); const awsContainerBook = responses[2].Item as Book; expect(awsContainerBook.isbn).toBe('978-4815607654'); expect(awsContainerBook.title).toBe('AWSã³ã³ããèšèšã»æ§ç¯[æ¬æ Œ]å ¥é'); expect(awsContainerBook.price).toBe(3300); expect(awsContainerBook.publicationDate).toBe('2021-10-21'); const awsInfraBook = responses[3].Item as Book; expect(awsInfraBook.isbn).toBe('978-4295006657'); expect(awsInfraBook.title).toBe( 'Amazon Web Servicesã€ã³ãã©ãµãŒãã¹æŽ»çšå€§å š ã·ã¹ãã æ§ç¯/èªååãããŒã¿ã¹ãã¢ãé«ä¿¡é Œå (impress top gear)' ); expect(awsInfraBook.price).toBe(5060); expect(awsInfraBook.publicationDate).toBe('2019-09-05');
DocumentClient#transactGet
ã§ã¯ãæå®ã§ããã®ã¯Get
ã®ã¿ã§ãã
ãã®æç¹ã§ãåããŒãã«ã«2ã¢ã€ãã ãã€ãããŸãã
test('current records', async () => { const peopleScanParams: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const peopleScanResult = await dynamodb.scan(peopleScanParams).promise(); expect(peopleScanResult.Count).toBe(2); const booksScanParams: DocumentClient.ScanInput = { TableName: 'Books', ConsistentRead: true, }; const booksScanResult = await dynamodb.scan(booksScanParams).promise(); expect(booksScanResult.Count).toBe(2); });
倱æããã±ãŒã¹ãè©ŠããŠã¿ã
ãŸãã¯ç°¡åã«è©ŠããŠã¿ãã®ã§ã次ã«å€±æãããããªã±ãŒã¹ãè©ŠããŠã¿ãŸãã
ä»åãçšæããããŒã¿26件å
šéšPut
ããŠã¿ãŸãã
test('transaction fail (over 25 records)', async () => { const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ); const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ); const allTransactionItems = people .map((p: Person) => ({ Put: { TableName: 'People', Item: p } })) .concat(books.map((b: Book) => ({ Put: { TableName: 'Books', Item: b } }))); const params: DocumentClient.TransactWriteItemsInput = { TransactItems: allTransactionItems, }; try { await dynamodb.transactWrite(params).promise(); throw new Error('test failed'); } catch (e) { const error = e as Error; expect(error.name).toBe('ValidationException'); expect(error.message).toBe( 'Member must have length less than or equal to 25' ); } const peopleScanParams: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const peopleScanResult = await dynamodb.scan(peopleScanParams).promise(); expect(peopleScanResult.Count).toBe(2); const booksScanParams: DocumentClient.ScanInput = { TableName: 'Books', ConsistentRead: true, }; const booksScanResult = await dynamodb.scan(booksScanParams).promise(); expect(booksScanResult.Count).toBe(2); });
People
ããŒãã«ã«14件ãBooks
ããŒãã«ã«12件ã§ããããããã²ãšã€ã®ãªã¯ãšã¹ãã«ãŸãšããŸãã
const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ); const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ); const allTransactionItems = people .map((p: Person) => ({ Put: { TableName: 'People', Item: p } })) .concat(books.map((b: Book) => ({ Put: { TableName: 'Books', Item: b } }))); const params: DocumentClient.TransactWriteItemsInput = { TransactItems: allTransactionItems, };
ããã§DocumentClient#transactWrite
ãå®è¡ãããšã25件ãè¶
ããŠãããšããããšã§ãšã©ãŒã«ãªããŸãã
try { await dynamodb.transactWrite(params).promise(); throw new Error('test failed'); } catch (e) { const error = e as Error; expect(error.name).toBe('ValidationException'); expect(error.message).toBe( 'Member must have length less than or equal to 25' ); }
ãã®æãããŒã¿ãäžéå端ã«å ¥ã£ããããªããšããããã€ã³ãã§ããã
const peopleScanParams: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const peopleScanResult = await dynamodb.scan(peopleScanParams).promise(); expect(peopleScanResult.Count).toBe(2); const booksScanParams: DocumentClient.ScanInput = { TableName: 'Books', ConsistentRead: true, }; const booksScanResult = await dynamodb.scan(booksScanParams).promise(); expect(booksScanResult.Count).toBe(2);
25件ã§æ¢ããŠããã°ãåé¡ãªãæåããŸãã
test('limit records(25) write', async () => { const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ); const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ); const allTransactionItems = people .map((p: Person) => ({ Put: { TableName: 'People', Item: p } })) .concat(books.map((b: Book) => ({ Put: { TableName: 'Books', Item: b } }))); const sliced = allTransactionItems.slice(0, 25); const params: DocumentClient.TransactWriteItemsInput = { TransactItems: sliced, }; await dynamodb.transactWrite(params).promise(); const peopleScanParams: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const peopleScanResult = await dynamodb.scan(peopleScanParams).promise(); expect(peopleScanResult.Count).toBe(14); const booksScanParams: DocumentClient.ScanInput = { TableName: 'Books', ConsistentRead: true, }; const booksScanResult = await dynamodb.scan(booksScanParams).promise(); expect(booksScanResult.Count).toBe(11); });
åãã¢ã€ãã ã«å¯ŸããŠãPut
ãUpdate
ããããŠã¿ãŸãã
test('same records operation', async () => { const params: DocumentClient.TransactWriteItemsInput = { TransactItems: [ { Put: { TableName: 'Books', Item: { isbn: '978-4815607654', title: 'AWSã³ã³ããèšèšã»æ§ç¯[æ¬æ Œ]å ¥é', price: 3300, publicationDate: '2021-10-21', }, }, }, { Update: { TableName: 'Books', Key: { isbn: '978-4815607654', }, UpdateExpression: 'set price = :price', ExpressionAttributeValues: { ':price': 6600, }, }, }, ], }; try { await dynamodb.transactWrite(params).promise(); throw new Error('test failed'); } catch (e) { const error = e as Error; expect(error.name).toBe('ValidationException'); expect(error.message).toBe( 'Transaction request cannot include multiple operations on one item' ); } });
ãã©ã³ã¶ã¯ã·ã§ã³å ã§åãã¢ã€ãã ã«å¯ŸããŠæäœããããšã¯èš±ãããŠããªãã®ã§ã倱æããŸãã
try { await dynamodb.transactWrite(params).promise(); throw new Error('test failed'); } catch (e) { const error = e as Error; expect(error.name).toBe('ValidationException'); expect(error.message).toBe( 'Transaction request cannot include multiple operations on one item' ); }
æåŸã«ããã©ã³ã¶ã¯ã·ã§ã³ã䜿ã£ãŠããŒã¿ãåé€ããŠãããŸãã«ããŸãã
test('delete all records', async () => { const people = JSON.parse( await fs.promises.readFile(`${__dirname}/people.json`, 'utf8') ) as Person[]; const peopleTransactWriteParams: DocumentClient.TransactWriteItemsInput = { TransactItems: people.map((p) => ({ Delete: { TableName: 'People', Key: { familyId: p.familyId, firstName: p.firstName, }, }, })), }; await dynamodb.transactWrite(peopleTransactWriteParams).promise(); const books = JSON.parse( await fs.promises.readFile(`${__dirname}/books.json`, 'utf8') ) as Book[]; const booksTransactWriteParams: DocumentClient.TransactWriteItemsInput = { TransactItems: books.map((b) => ({ Delete: { TableName: 'Books', Key: { isbn: b.isbn, }, }, })), }; await dynamodb.transactWrite(booksTransactWriteParams).promise(); const peopleScanParams: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const peopleScanResult = await dynamodb.scan(peopleScanParams).promise(); expect(peopleScanResult.Count).toBe(0); const booksScanParams: DocumentClient.ScanInput = { TableName: 'Books', ConsistentRead: true, }; const booksScanResult = await dynamodb.scan(booksScanParams).promise(); expect(booksScanResult.Count).toBe(0); });
ãŸãšã
Amazon DynamoDBã®ãã©ã³ã¶ã¯ã·ã§ã³ãç°¡åã«è©ŠããŠã¿ãŸããã
ãã£ããèšããšãã¢ãããã¯ãªãããçãªåŠçãšããæãã§ããããã®ä»ã«ãããããç¹åŸŽãããããã§ããã
ãªããšãªãæŠèŠã¯ããã£ãã®ã§ããããšããŸãããã