asw-api 使ってみた
特徴
Java SDKのつらいところを避けるアプローチ
具体的にはJavaのsdkは主にオブジェクト指向であることに起因して以下のコストがかかる。
使いたいサービスのクラスのJavadocを探す
そのクラスのコンストラクタの使い方、引数の意味を理解する
行いたいオペレーションに対応するメソッドを探す
そのメソッドの引数の型と意味を理解する
artifactが巨大(オブジェクト指向であることとは直接は関係ない)
amazonicaをdependencyに足すとダウンロードが永遠に終わらない
使いたいサービスに必要な部分のdepsだけを指定するのめっちゃだるい
このようなつらい内部実装をClojureっぽいインターフェースでラップしたとしても次のような問題がままある
Clojureラッパーでカバーできない部分は結局Java sdkのレベルに降りる必要がある
Clojureインターフェースの使い方がよく分からない
殆どの場合、AWSにHTTPリクエストを投げたいだけなのに。。。
=>リクエストに含めるkeyの意味が分かれば使える
aws-apiではAWSの公式のJS sdkのレポジトリのapi仕様から自動生成しているため以下を実現できている
サービスを跨いで一貫したインターフェース
e.g. s3を使う場合でも、他のサービスを使う場合でもapiの使い方が同じ!
データ指向
À la carte
e.g. s3だけ使う場合はs3のartifactだけを指定することができる
使ってみる
仕事で必要になるためtranslateを使ってみることにする
deps
こんな感じ
code:clojure
com.cognitect.aws/api {:mvn/version "0.8.166"}
com.cognitect.aws/endpoints {:mvn/version "1.1.11.475"}
com.cognitect.aws/translate {:mvn/version "669.2.364.0"}
apiとendpointは使うサービスに関係無く依存する。
それ以外は使うapiのartifactだけを指定する
基本的な使い方
ネームスペースをrequire:
(require '[cognitect.aws.client.api :as aws])
使うサービスのクライアントを作る
(def translate (aws/client {:api :translate}))
使える操作の一覧を確認する
パラメータの型と必須かどうかがデータでわかるので親切
code:clojure
(aws/ops translate)
=>
{:DeleteTerminology {:name "DeleteTerminology", :documentation "<p>A synchronous action that deletes a custom terminology.</p>", :request {:Name string}, :required :Name, :response nil}, :GetTerminology {:name "GetTerminology", :documentation "<p>Retrieves a custom terminology.</p>", :request {:Name string, :TerminologyDataFormat string}, :required :Name :TerminologyDataFormat, :response {:TerminologyProperties {:SizeBytes integer, :CreatedAt timestamp, :LastUpdatedAt timestamp, :SourceLanguageCode string, :EncryptionKey {:Type string, :Id string}, :TargetLanguageCodes :seq-of string, :TermCount integer, :Arn string, :Name string, :Description string}, :TerminologyDataLocation {:RepositoryType string, :Location string}}}, :ImportTerminology {:name "ImportTerminology", :documentation "<p>Creates or updates a custom terminology, depending on whether or not one already exists for the given terminology name. Importing a terminology with the same name as an existing one will merge the terminologies based on the chosen merge strategy. Currently, the only supported merge strategy is OVERWRITE, and so the imported terminology will overwrite an existing terminology of the same name.</p> <p>If you import a terminology that overwrites an existing one, the new terminology take up to 10 minutes to fully propagate and be available for use in a translation due to cache policies with the DataPlane service that performs the translations.</p>", :request {:Name string, :MergeStrategy string, :Description string, :TerminologyData {:File blob, :Format string}, :EncryptionKey {:Type string, :Id string}}, :required :Name :MergeStrategy :TerminologyData, :response {:TerminologyProperties {:SizeBytes integer, :CreatedAt timestamp, :LastUpdatedAt timestamp, :SourceLanguageCode string, :EncryptionKey {:Type string, :Id string}, :TargetLanguageCodes :seq-of string, :TermCount integer, :Arn string, :Name string, :Description string}}}, :ListTerminologies {:name "ListTerminologies", :documentation "<p>Provides a list of custom terminologies associated with your account.</p>", :request {:NextToken string, :MaxResults integer}, :required nil, :response {:TerminologyPropertiesList [:seq-of {:SizeBytes integer, :CreatedAt timestamp, :LastUpdatedAt timestamp, :SourceLanguageCode string, :EncryptionKey {:Type string, :Id string}, :TargetLanguageCodes :seq-of string, :TermCount integer, :Arn string, :Name string, :Description string}], :NextToken string}}, :TranslateText {:name "TranslateText", :documentation "<p>Translates input text from the source language to the target language. It is not necessary to use English (en) as either the source or the target language but not all language combinations are supported by Amazon Translate. For more information, see <a href=\"http://docs.aws.amazon.com/translate/latest/dg/pairs.html\">Supported Language Pairs</a>.</p> <ul> <li> <p>Arabic (ar)</p> </li> <li> <p>Chinese (Simplified) (zh)</p> </li> <li> <p>Chinese (Traditional) (zh-TW)</p> </li> <li> <p>Czech (cs)</p> </li> <li> <p>Danish (da)</p> </li> <li> <p>Dutch (nl)</p> </li> <li> <p>English (en)</p> </li> <li> <p>Finnish (fi)</p> </li> <li> <p>French (fr)</p> </li> <li> <p>German (de)</p> </li> <li> <p>Hebrew (he)</p> </li> <li> <p>Indonesian (id)</p> </li> <li> <p>Italian (it)</p> </li> <li> <p>Japanese (ja)</p> </li> <li> <p>Korean (ko)</p> </li> <li> <p>Polish (pl)</p> </li> <li> <p>Portuguese (pt)</p> </li> <li> <p>Russian (ru)</p> </li> <li> <p>Spanish (es)</p> </li> <li> <p>Swedish (sv)</p> </li> <li> <p>Turkish (tr)</p> </li> </ul> <p>To have Amazon Translate determine the source language of your text, you can specify <code>auto</code> in the <code>SourceLanguageCode</code> field. If you specify <code>auto</code>, Amazon Translate will call Amazon Comprehend to determine the source language.</p>", :request {:Text string, :TerminologyNames :seq-of string, :SourceLanguageCode string, :TargetLanguageCode string}, :required :Text :SourceLanguageCode :TargetLanguageCode, :response {:TranslatedText string, :SourceLanguageCode string, :TargetLanguageCode string, :AppliedTerminologies [:seq-of {:Name string, :Terms :seq-of {:SourceText string, :TargetText string}}]}}} 操作を行なってみる
code:clojure
(aws/invoke translate
{:op :TranslateText
:request {:Text "こんにちは"
:SourceLanguageCode "ja"
:TargetLanguageCode "en"}})
=> {:SourceLanguageCode "ja", :TargetLanguageCode "en", :TranslatedText "Hello"}
caveats
Clojure 1.10 must
datafyableを使っているため
AWS_REGIONの設定
リージョンに依存するサービスの場合、何かしらの方法でリージョンを指定する必要がある。指定しないと例外が出る。
今回は環境変数を指定した
感想
素晴しい
以前はamazonicaを使っていたが、初めて使うサービスでは絶対こちらを利用していく
学習コストが下がりまくっているのでどんどんawsを使いたくなるのを感じる