Skip to content

Commit

Permalink
Trying lower implementation cost of getting S3 bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
rtyley committed Dec 12, 2024
1 parent 8561f33 commit 00e616b
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 39 deletions.
8 changes: 0 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ name := "facia-api-client"

description := "Scala client for The Guardian's Facia JSON API"

ThisBuild / scalaVersion := "2.13.14"

val sonatypeReleaseSettings = Seq(
// releaseVersion := fromAggregatedAssessedCompatibilityWithLatestRelease().value,
releaseCrossBuild := true, // true if you cross-build the project for multiple Scala versions
Expand Down Expand Up @@ -42,14 +40,8 @@ lazy val fapiClient_core = (project in file("fapi-client-core")).settings(
artifactProducingSettings(supportScala3 = true)
)

lazy val fapiClient_s3_sdk_v2 = (project in file("fapi-s3-sdk-v2")).dependsOn(fapiClient_core).settings(
libraryDependencies += eTagCachingS3SdkV2,
artifactProducingSettings(supportScala3 = true)
)

lazy val root = (project in file(".")).aggregate(
fapiClient_core,
fapiClient_s3_sdk_v2,
faciaJson_play28,
faciaJson_play29,
faciaJson_play30,
Expand Down
38 changes: 20 additions & 18 deletions facia-json/src/main/scala/com/gu/facia/client/ApiClient.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.gu.facia.client

import com.gu.etagcaching.FreshnessPolicy.AlwaysWaitForRefreshedValue
import com.gu.etagcaching.aws.s3.ObjectId
import com.gu.etagcaching.aws.s3.{ObjectId, S3ByteArrayFetching}
import com.gu.etagcaching.fetching.Fetching
import com.gu.etagcaching.{ConfigCache, ETagCache}
import com.gu.facia.client.models.{CollectionJson, ConfigJson}
Expand Down Expand Up @@ -52,29 +52,31 @@ object ApiClient {
throw JsonDeserialisationError(s"Could not deserialize JSON")
}

/**
* @param s3Fetching eg `S3ObjectFetching.byteArrayWith(s3AsyncClient)`
*/
def withCaching(
bucket: String,
environment: Environment,
s3Fetching: Fetching[ObjectId, Array[Byte]], // Eg S3ObjectFetching(s3AsyncClient, Bytes).mapResponse(_.asByteArray())
s3Fetching: S3ByteArrayFetching,
configureCollectionCache: ConfigCache = _.maximumSize(10000) // at most 1GB RAM worst case
)(implicit ec: ExecutionContext): ApiClient =
new ApiClient {
private val fetching =
s3Fetching.keyOn[String](path => ObjectId(bucket, path))
)(implicit ec: ExecutionContext): ApiClient = new ApiClient {
private val fetching =
s3Fetching.keyOn[String](path => ObjectId(bucket, path))

def eTagCache[B: Format](configureCache: ConfigCache) = new ETagCache(
fetching.thenParsing(parseBytes[B]),
AlwaysWaitForRefreshedValue,
configureCache
)
def eTagCache[B: Format](configureCache: ConfigCache) = new ETagCache(
fetching.thenParsing(parseBytes[B]),
AlwaysWaitForRefreshedValue,
configureCache
)

private val configCache = eTagCache[ConfigJson](_.maximumSize(1))
private val collectionCache = eTagCache[CollectionJson](configureCollectionCache)
private val configCache = eTagCache[ConfigJson](_.maximumSize(1))
private val collectionCache = eTagCache[CollectionJson](configureCollectionCache)

override def config: Future[ConfigJson] =
configCache.get(environment.configS3Path).map(getOrWarnAboutMissingConfig)
override def config: Future[ConfigJson] =
configCache.get(environment.configS3Path).map(getOrWarnAboutMissingConfig)

override def collection(id: String): Future[Option[CollectionJson]] =
collectionCache.get(environment.collectionS3Path(id))
}
override def collection(id: String): Future[Option[CollectionJson]] =
collectionCache.get(environment.collectionS3Path(id))
}
}

This file was deleted.

16 changes: 16 additions & 0 deletions fapi-client-core/src/main/scala/com/gu/facia/client/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gu.facia

import com.gu.etagcaching.aws.s3.ObjectId
import com.gu.etagcaching.fetching.Fetching

package object client {
/**
* AWS SDK v2
*
* Add "com.gu.etag-caching" %% "aws-s3-sdk-v2" as dependency,
* import com.gu.etagcaching.aws.sdkv2.s3.S3ObjectFetching
*
* S3ObjectFetching.byteArrayWith(s3AsyncClient)
*/
type S3FetchBehaviour = Fetching[ObjectId, Array[Byte]]
}
8 changes: 5 additions & 3 deletions fapi-client/src/test/scala/lib/IntegrationTestConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ trait IntegrationTestConfig extends ExecutionContext {
def credentialsForDevAndCI(devProfile: String, ciCreds: AwsCredentialsProvider): AwsCredentialsProviderChain =
AwsCredentialsProviderChain.of(ciCreds, ProfileCredentialsProvider.builder().profileName(devProfile).build())

private val s3AsyncClient: S3AsyncClient = S3AsyncClient.builder()
.region(Region.EU_WEST_1)
.credentialsProvider(credentialsForDevAndCI(awsProfileName, EnvironmentVariableCredentialsProvider.create())).build()

implicit val apiClient: ApiClient = ApiClient.withCaching(
"facia-tool-store",
Environment.Dev,
S3ObjectFetching(S3AsyncClient.builder()
.region(Region.EU_WEST_1)
.credentialsProvider(credentialsForDevAndCI(awsProfileName, EnvironmentVariableCredentialsProvider.create())).build(), Bytes).mapResponse(_.asByteArray())
S3ObjectFetching.byteArrayWith(s3AsyncClient)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import software.amazon.awssdk.services.s3.model.NoSuchKeyException

case class AwsSdkV2(s3AsyncClient: S3AsyncClient) extends S3FetchBehaviour {
override val fetching: Fetching[ObjectId, Array[Byte]] =
S3ObjectFetching(s3AsyncClient, Bytes).mapResponse(_.asByteArray())
com.gu.etagcaching.aws.sdkv2.s3.S3ObjectFetching.byteArrayWith(s3AsyncClient)

}
2 changes: 1 addition & 1 deletion project/dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import sbt._

object Dependencies {
val capiVersion = "32.0.0"
val eTagCachingVersion = "5.0.1"
val eTagCachingVersion = "5.0.3-SNAPSHOT"

val awsS3SdkV1 = "com.amazonaws" % "aws-java-sdk-s3" % "1.12.765"
val eTagCachingS3Base = "com.gu.etag-caching" %% "aws-s3-base" % eTagCachingVersion
Expand Down

0 comments on commit 00e616b

Please sign in to comment.