Skip to content

Commit

Permalink
Merge pull request #139 from mdsol/tech/update_guava_cache_to_caffeine
Browse files Browse the repository at this point in the history
Tech/update guava cache to caffeine
  • Loading branch information
jdepassos-mdsol authored Mar 23, 2022
2 parents 1997e29 + c70580a commit b21e7f7
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: scala
jdk:
- openjdk8
- openjdk11
services:
- docker
env:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Swap scalacache-guava to scalacache-caffeine
- Add an IO interface for ClientPublicKeyProvider

## [7.0.1] - 2021-09-28
### Changed
Upgraded scala cats lib, and fixed resulting breakages. Also updated sbt plugins.
Expand Down
7 changes: 3 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ lazy val `mauth-sender-sttp-akka-http` = scalaModuleProject("mauth-sender-sttp-a
publishSettings,
libraryDependencies ++=
Dependencies.compile(catsEffect, akkaHttp, akkaStream, scalaLibCompat, sttp, scalaLogging).map(withExclusions) ++
Dependencies.test(scalaMock, scalaTest, wiremock, sttpAkkaHttpBackend).map(withExclusions),
// TODO remove once published
mimaPreviousArtifacts := Set.empty
Dependencies.test(scalaMock, scalaTest, wiremock, sttpAkkaHttpBackend).map(withExclusions)
)

lazy val `mauth-authenticator` = javaModuleProject("mauth-authenticator")
Expand All @@ -123,7 +121,8 @@ lazy val `mauth-authenticator-scala` = scalaModuleProject("mauth-authenticator-s
.settings(
publishSettings,
libraryDependencies ++=
Dependencies.test(logbackClassic, scalaMock, scalaTest, scalaLibCompat).map(withExclusions)
Dependencies.test(logbackClassic, scalaMock, scalaTest, scalaLibCompat).map(withExclusions) ++
Dependencies.compile(catsEffect).map(withExclusions)
)

lazy val `mauth-authenticator-apachehttp` = javaModuleProject("mauth-authenticator-apachehttp")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
package com.mdsol.mauth.akka.http

import java.net.URI
import java.security.PublicKey
import java.util.UUID

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import cats.effect.IO
import cats.effect.unsafe.implicits.global
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.benmanes.caffeine.cache.Caffeine
import com.mdsol.mauth.http.HttpClient
import com.mdsol.mauth.http.Implicits._
import com.mdsol.mauth.models.UnsignedRequest
import com.mdsol.mauth.scaladsl.utils.ClientPublicKeyProvider
import com.mdsol.mauth.util.MAuthKeysHelper
import com.mdsol.mauth.{AuthenticatorConfiguration, MAuthRequestSigner}
import com.typesafe.scalalogging.StrictLogging
import scalacache.guava._
import scalacache.caffeine.CaffeineCache
import scalacache.memoization._
import scalacache.modes.scalaFuture._
import com.mdsol.mauth.http.Implicits._
import scalacache.{Cache, Entry}

import java.net.URI
import java.security.PublicKey
import java.util.UUID
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success, Try}

class MauthPublicKeyProvider(configuration: AuthenticatorConfiguration, signer: MAuthRequestSigner)(implicit
Expand All @@ -31,48 +33,52 @@ class MauthPublicKeyProvider(configuration: AuthenticatorConfiguration, signer:
) extends ClientPublicKeyProvider
with StrictLogging {

implicit val guavaCache: GuavaCache[Option[PublicKey]] = GuavaCache[Option[PublicKey]]
private val cCache = Caffeine.newBuilder().build[String, Entry[Option[PublicKey]]]()
implicit val caffeineCache: Cache[IO, String, Option[PublicKey]] = CaffeineCache[IO, String, Option[PublicKey]](underlying = cCache)
protected val mapper = new ObjectMapper

/** Returns the associated public key for a given application UUID.
*
* @param appUUID , UUID of the application for which we want to retrieve its public key.
* @return { @link PublicKey} registered in MAuth for the application with given appUUID.
*/
override def getPublicKey(appUUID: UUID): Future[Option[PublicKey]] = memoizeF(Some(configuration.getTimeToLive.seconds)) {
override def getPublicKey(appUUID: UUID): Future[Option[PublicKey]] =
getPublicKeyIO(appUUID).unsafeToFuture()

override def getPublicKeyIO(appUUID: UUID): IO[Option[PublicKey]] = memoizeF(Some(configuration.getTimeToLive.seconds)) {
val signedRequest = signer.signRequest(UnsignedRequest.noBody("GET", new URI(configuration.getBaseUrl + getRequestUrlPath(appUUID)), headers = Map.empty))
retrievePublicKey()(HttpClient.call(signedRequest.toAkkaHttpRequest))
retrievePublicKey()(IO.fromFuture(IO(HttpClient.call(signedRequest.toAkkaHttpRequest))))
}

protected def retrievePublicKey()(mauthPublicKeyFetcher: => Future[HttpResponse]): Future[Option[PublicKey]] = {
val promise = Promise[Option[PublicKey]]()
protected def retrievePublicKey()(mauthPublicKeyFetcher: => IO[HttpResponse]): IO[Option[PublicKey]] = {
mauthPublicKeyFetcher
.flatMap { response =>
Unmarshal(response.entity)
.to[String]
.map { body =>
if (response.status == StatusCodes.OK) {
Try(MAuthKeysHelper.getPublicKeyFromString(mapper.readTree(body).findValue("public_key_str").asText)) match {
case Success(publicKey) => promise.success(Some(publicKey))
case Failure(error) =>
logger.error("Converting string to Public Key failed", error)
promise.success(None)
}
} else {
logger.error(s"Unexpected response returned by server -- status: ${response.status} response: $body")
promise.success(None)
IO.fromFuture(
IO(
Unmarshal(response.entity)
.to[String]
)
).map { body =>
if (response.status == StatusCodes.OK) {
Try(MAuthKeysHelper.getPublicKeyFromString(mapper.readTree(body).findValue("public_key_str").asText)) match {
case Success(publicKey) => Some(publicKey)
case Failure(error) =>
logger.error("Converting string to Public Key failed", error)
None
}
} else {
logger.error(s"Unexpected response returned by server -- status: ${response.status} response: $body")
None
}
.recover { case error =>
logger.error("Request to get MAuth public key couldn't be signed", error)
promise.success(None)
}
}.handleError { error: Throwable =>
logger.error("Request to get MAuth public key couldn't be signed", error)
None
}
}
.recover { case error =>
.handleError { error: Throwable =>
logger.error("Request to get MAuth public key couldn't be completed", error)
promise.success(None)
None
}
promise.future
}

protected def getRequestUrlPath(appUUID: UUID): String =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.mdsol.mauth.scaladsl.utils

import cats.effect.IO

import java.security.PublicKey
import java.util.UUID

Expand All @@ -13,4 +15,6 @@ trait ClientPublicKeyProvider {
* @return Future of { @link PublicKey} registered in MAuth for the application with given appUUID.
*/
def getPublicKey(appUUID: UUID): Future[Option[PublicKey]]

def getPublicKeyIO(appUUID: UUID): IO[Option[PublicKey]]
}
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object Dependencies extends DependencyUtils {
val logbackCore: ModuleID = "ch.qos.logback" % "logback-core" % Version.logback
val slf4jApi: ModuleID = "org.slf4j" % "slf4j-api" % "1.7.30"
val typeSafeConfig: ModuleID = "com.typesafe" % "config" % "1.4.1"
val scalaCache: ModuleID = "com.github.cb372" %% "scalacache-guava" % "0.28.0"
val scalaCache: ModuleID = "com.github.cb372" %% "scalacache-caffeine" % "1.0.0-M6"
val scalaLogging: ModuleID = "com.typesafe.scala-logging" %% "scala-logging" % "3.9.3"
val catsEffect: ModuleID = "org.typelevel" %% "cats-effect" % "3.2.9"
val sttp: ModuleID = "com.softwaremill.sttp.client3" %% "core" % Version.sttp
Expand Down

0 comments on commit b21e7f7

Please sign in to comment.