From bc1bffc3459544e635c3b965ce8eef6c0bb160c1 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 10 May 2019 19:35:35 +0100 Subject: [PATCH] [awssdk] Rewritten and simplified AWS SDK interface --- .../s3thorp/awssdk/CatsIOS3Client.scala | 9 ---- ...ncClient.scala => JavaClientWrapper.scala} | 5 +- .../awssdk/S3CatsIOClientProvider.scala | 9 ---- .../net/kemitix/s3thorp/awssdk/S3Client.scala | 7 ++- ...tiveS3Client.scala => ThropS3Client.scala} | 14 +++--- .../scala/net/kemitix/s3thorp/SyncSuite.scala | 7 ++- .../s3thorp/awssdk/ReactiveS3ClientTest.scala | 48 ------------------- .../s3thorp/awssdk/S3ClientSuite.scala | 45 +++++++++++++++++ 8 files changed, 65 insertions(+), 79 deletions(-) delete mode 100644 src/main/scala/net/kemitix/s3thorp/awssdk/CatsIOS3Client.scala rename src/main/scala/net/kemitix/s3thorp/awssdk/{UnderlyingS3AsyncClient.scala => JavaClientWrapper.scala} (63%) delete mode 100644 src/main/scala/net/kemitix/s3thorp/awssdk/S3CatsIOClientProvider.scala rename src/main/scala/net/kemitix/s3thorp/awssdk/{ReactiveS3Client.scala => ThropS3Client.scala} (59%) delete mode 100644 src/test/scala/net/kemitix/s3thorp/awssdk/ReactiveS3ClientTest.scala create mode 100644 src/test/scala/net/kemitix/s3thorp/awssdk/S3ClientSuite.scala diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/CatsIOS3Client.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/CatsIOS3Client.scala deleted file mode 100644 index 46ca247..0000000 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/CatsIOS3Client.scala +++ /dev/null @@ -1,9 +0,0 @@ -package net.kemitix.s3thorp.awssdk - -import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient - -trait CatsIOS3Client extends S3CatsIOClientProvider { - - def s3Client = S3CatsIOClient(underlying) - -} diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/UnderlyingS3AsyncClient.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/JavaClientWrapper.scala similarity index 63% rename from src/main/scala/net/kemitix/s3thorp/awssdk/UnderlyingS3AsyncClient.scala rename to src/main/scala/net/kemitix/s3thorp/awssdk/JavaClientWrapper.scala index cb67314..155ea78 100644 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/UnderlyingS3AsyncClient.scala +++ b/src/main/scala/net/kemitix/s3thorp/awssdk/JavaClientWrapper.scala @@ -4,8 +4,9 @@ import com.github.j5ik2o.reactive.aws.s3.S3AsyncClient import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient import software.amazon.awssdk.services.s3.{S3AsyncClient => JavaS3AsyncClient} -trait UnderlyingS3AsyncClient extends S3CatsIOClient{ +trait JavaClientWrapper extends S3CatsIOClient { - override val underlying: S3AsyncClient = S3AsyncClient(JavaS3AsyncClient.create) + override val underlying: S3AsyncClient = + S3AsyncClient(JavaS3AsyncClient.create) } diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/S3CatsIOClientProvider.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/S3CatsIOClientProvider.scala deleted file mode 100644 index dd73dc1..0000000 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/S3CatsIOClientProvider.scala +++ /dev/null @@ -1,9 +0,0 @@ -package net.kemitix.s3thorp.awssdk - -import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient - -trait S3CatsIOClientProvider extends UnderlyingS3AsyncClient { - - def s3Client: S3CatsIOClient - -} diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala index 3e55c7c..5c788cb 100644 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala +++ b/src/main/scala/net/kemitix/s3thorp/awssdk/S3Client.scala @@ -1,7 +1,8 @@ package net.kemitix.s3thorp.awssdk import cats.effect.IO -import net.kemitix.s3thorp.Sync.{Bucket, MD5Hash, LastModified, LocalFile, RemoteKey} +import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient +import net.kemitix.s3thorp.Sync.{Bucket, LastModified, LocalFile, MD5Hash, RemoteKey} trait S3Client { @@ -13,6 +14,8 @@ trait S3Client { object S3Client { - val defaultClient: S3Client = new ReactiveS3Client + val defaultClient: S3Client = + new ThropS3Client( + S3CatsIOClient(new JavaClientWrapper {}.underlying)) } \ No newline at end of file diff --git a/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala b/src/main/scala/net/kemitix/s3thorp/awssdk/ThropS3Client.scala similarity index 59% rename from src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala rename to src/main/scala/net/kemitix/s3thorp/awssdk/ThropS3Client.scala index 0abbfc9..6287f3e 100644 --- a/src/main/scala/net/kemitix/s3thorp/awssdk/ReactiveS3Client.scala +++ b/src/main/scala/net/kemitix/s3thorp/awssdk/ThropS3Client.scala @@ -1,27 +1,27 @@ package net.kemitix.s3thorp.awssdk import cats.effect.IO -import net.kemitix.s3thorp.Sync.{Bucket, LocalFile, RemoteKey} +import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient +import net.kemitix.s3thorp.Sync.{Bucket, LastModified, LocalFile, MD5Hash, RemoteKey} import software.amazon.awssdk.core.async.AsyncRequestBody import software.amazon.awssdk.services.s3.model.{HeadObjectRequest, PutObjectRequest} -private class ReactiveS3Client - extends S3Client - with CatsIOS3Client { +private class ThropS3Client(s3Client: S3CatsIOClient) extends S3Client { - override def objectHead(bucket: Bucket, remoteKey: RemoteKey) = { + def objectHead(bucket: Bucket, remoteKey: RemoteKey): IO[Option[(MD5Hash, LastModified)]] = { val request = HeadObjectRequest.builder().bucket(bucket).key(remoteKey).build() s3Client.headObject(request).attempt.map { case Right(response) => Some((response.eTag(), response.lastModified())) - case Left(_) =>None + case Left(_) => None } } - override def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] = { + def upload(localFile: LocalFile, bucket: Bucket, remoteKey: RemoteKey): IO[Unit] = { val request = PutObjectRequest.builder().bucket(bucket).key(remoteKey).build() val body = AsyncRequestBody.fromFile(localFile) for { _ <- s3Client.putObject(request, body) } yield () } + } diff --git a/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala b/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala index 8c6c60b..c921b3a 100644 --- a/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala +++ b/src/test/scala/net/kemitix/s3thorp/SyncSuite.scala @@ -12,11 +12,14 @@ class SyncSuite extends FunSpec { val hash = "hash" val lastModified = Instant.now() val sync = new Sync(new S3Client with DummyS3Client { - override def objectHead(bucket: String, key: String) = IO(Some((hash, lastModified))) + override def objectHead(bucket: String, key: String) = + IO(Some((hash, lastModified))) }) describe("objectHead") { it("return the hash and lastModified expected") { - assertResult(Some((hash, lastModified)))(sync.objectHead("", "").unsafeRunSync()) + assertResult(Some((hash, lastModified)))( + sync.objectHead("", ""). + unsafeRunSync()) } } } diff --git a/src/test/scala/net/kemitix/s3thorp/awssdk/ReactiveS3ClientTest.scala b/src/test/scala/net/kemitix/s3thorp/awssdk/ReactiveS3ClientTest.scala deleted file mode 100644 index 9b37596..0000000 --- a/src/test/scala/net/kemitix/s3thorp/awssdk/ReactiveS3ClientTest.scala +++ /dev/null @@ -1,48 +0,0 @@ -package net.kemitix.s3thorp.awssdk - -import java.time.Instant - -import cats.effect.IO -import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient -import org.scalatest.FunSpec -import software.amazon.awssdk.services.s3.model.{HeadObjectRequest, HeadObjectResponse, NoSuchKeyException} - -class ReactiveS3ClientTest extends FunSpec { - - describe("testObjectHead") { - def invoke(self: S3Client) = { - self.objectHead("bucket", "remoteKey").unsafeRunSync() - } - - describe("when underlying client response is okay") { - val expectedHash = "hash" - val expectedLastModified = Instant.now - new ReactiveS3Client { self: S3Client => { - it("should return Some(expected values)") { - assertResult(Some((expectedHash, expectedLastModified)))(invoke(self)) - } - } - override def s3Client: S3CatsIOClient = new S3CatsIOClient with UnderlyingS3AsyncClient { - override def headObject(headObjectRequest: HeadObjectRequest): IO[HeadObjectResponse] = - IO(HeadObjectResponse.builder(). - eTag(expectedHash). - lastModified(expectedLastModified). - build()) - } - } - } - - describe("when underlying client throws NoSuchKeyException") { - new ReactiveS3Client { self: S3Client => - it("should return None") { - assertResult(None)(invoke(self)) - } - override def s3Client: S3CatsIOClient = new S3CatsIOClient with UnderlyingS3AsyncClient { - override def headObject(headObjectRequest: HeadObjectRequest): IO[HeadObjectResponse] = - throw NoSuchKeyException.builder().build() - } - } - } - } - -} diff --git a/src/test/scala/net/kemitix/s3thorp/awssdk/S3ClientSuite.scala b/src/test/scala/net/kemitix/s3thorp/awssdk/S3ClientSuite.scala new file mode 100644 index 0000000..a0a3bb1 --- /dev/null +++ b/src/test/scala/net/kemitix/s3thorp/awssdk/S3ClientSuite.scala @@ -0,0 +1,45 @@ +package net.kemitix.s3thorp.awssdk + +import java.time.Instant + +import cats.effect.IO +import com.github.j5ik2o.reactive.aws.s3.cats.S3CatsIOClient +import org.scalatest.FunSpec +import software.amazon.awssdk.services.s3.model.{HeadObjectRequest, HeadObjectResponse, NoSuchKeyException} + +class S3ClientSuite extends FunSpec { + + describe("testObjectHead") { + def invoke(self: S3Client) = { + self.objectHead("bucket", "remoteKey").unsafeRunSync() + } + + describe("when underlying client response is okay") { + val expectedHash = "hash" + val expectedLastModified = Instant.now + val underlyingClient = new S3CatsIOClient with JavaClientWrapper { + override def headObject(headObjectRequest: HeadObjectRequest) = + IO(HeadObjectResponse.builder(). + eTag(expectedHash). + lastModified(expectedLastModified). + build()) + } + val s3Client = new ThropS3Client(underlyingClient) + it("should return Some(expected values)") { + assertResult(Some((expectedHash, expectedLastModified)))(invoke(s3Client)) + } + } + + describe("when underlying client throws NoSuchKeyException") { + val underlyingClient = new S3CatsIOClient with JavaClientWrapper { + override def headObject(headObjectRequest: HeadObjectRequest): IO[HeadObjectResponse] = + IO(throw NoSuchKeyException.builder().build()) + } + val s3Client = new ThropS3Client(underlyingClient) + it("should return None") { + assertResult(None)(invoke(s3Client)) + } + } + + } +}