AmazonS3AsyncClientは存在しない 〜 TransferManagerの紹介

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

よく訓練されたアップル信者、都元です。自分、まいどまいどヘヴィーなエントリばっかり書いてしまう癖があるので、たまにはライトな奴を投下しようと思います。

AWS SDK for Javaには、通常のAPIラッパー(例えば、AmazonEC2Client/AmazonEC2)と、非同期処理対応のラッパー(例えば、AmazonEC2AsyncClient/AmazonEC2Async)がセットで用意されている事が多いです。通常処理はResponseを返すのに対し、非同期APIではFuture<Response>を返すような仕組みになっています。

ところで、AmazonS3については、AmazonS3AsyncClient/AmazonS3Asyncというクラスが提供されていません。本エントリは、「無い!!何で!?」と思って「AmazonS3AsyncClient」というキーワードでググった人に見つけてもらえればなぁ、と願ってをります。

S3の非同期処理

とは言え、S3の非同期処理はサポートされていないわけではなく、なぜかTransferManagerという名前で提供されています。しかも、単にFutureで対応するようなプリミティブなものではなく、もっと高水準の処理(ステータスのチェック、転送完了イベントのハンドリング、転送のキャンセル等)が用意されているのが嬉しいところです。だから命名パターンから外れたのでしょうかね。

例えば、ファイルのアップロードはこんな感じ。uploadメソッドは非同期で実行され、アップロードが完了しなくても処理が帰ってきます。その後、アップロードが完了するまで標準出力に進捗を表示し続けます。

TransferManager transferManager = new TransferManager(credentials);
Upload upload = transferManager.upload(bucketName, file.getName(), file);
while (upload.isDone() == false) {
  System.out.println(upload.getProgress().getPercentTransfered() + "%");
}

また、リスナを仕掛けて同様の機能を実現することもできます。

TransferManager transferManager = new TransferManager(credentials);
final Upload upload = transferManager.upload(bucketName, file.getName(), file);
upload.setProgressListener(new ProgressListener() {
    
    @Override
    public void progressChanged(ProgressEvent progressEvent) {
        System.out.println(upload.getProgress().getPercentTransfered() + "%");
 
        if (progressEvent.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE) {
            System.out.println("Upload complete!!!");
        }
    }
};
 
upload.waitForCompletion();

その他、TransferManagerはアップロード時にそのファイルサイズ等を考慮し、可能であればファイルを複数のパートに分割し、並列アップロードによってパフォーマンスを上げる、といったことまでサポートしてくれます。この方式だと、万が一通信エラーが発生した場合でも全体を再転送する必要はなく、再試行すべきなのは1つのパートだけ、という利点もあります。

小ネタでした。