Skip to content

Commit

Permalink
chore: manual pass to make project compile with CE3 ecosystem
Browse files Browse the repository at this point in the history
  • Loading branch information
samidalouche committed Sep 4, 2023
1 parent 746b6cf commit 683a6e2
Show file tree
Hide file tree
Showing 15 changed files with 131 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,31 @@ import doobie.Transactor
import doobie.hikari.HikariTransactor
import doobie.util.ExecutionContexts
import io.narrative.common.ssm.SSMResources
import org.http4s.blaze.client.BlazeClientBuilder
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.client.Client

import scala.concurrent.ExecutionContext

final case class Resources(
awsCredentials: AWSCredentialsProvider,
blocker: Blocker,
client: Client[IO],
kms: AWSKMS,
serverEC: ExecutionContext,
ssm: AWSSimpleSystemsManagement,
xa: Transactor[IO]
) {
def resolve(value: Config.Value): IO[String] =
Resources.resolve(blocker, ssm, value)
Resources.resolve(ssm, value)
}
object Resources extends LazyLogging {
def apply(config: Config): Resource[IO, Resources] =
for {
blocker <- Resource.unit[IO]
awsCredentials = new DefaultAWSCredentialsProviderChain()
client <- BlazeClientBuilder[IO](blocker.blockingContext).resource
serverEC <- ExecutionContexts.fixedThreadPool[IO](64)
ssm <- SSMResources.ssmClient(logger.underlying, blocker, awsCredentials)
awsCredentials <- Resource.eval(IO.blocking(new DefaultAWSCredentialsProviderChain()))
client <- EmberClientBuilder.default[IO].build
ssm <- SSMResources.ssmClient(logger.underlying, awsCredentials)
kms <- awsKms(awsCredentials)
xa <- transactor(blocker, ssm, config.database)
xa <- transactor(ssm, config.database)
} yield Resources(
awsCredentials = awsCredentials,
blocker = blocker,
client = client,
kms = kms,
serverEC = serverEC,
ssm = ssm,
xa = xa
)
Expand All @@ -54,12 +46,11 @@ object Resources extends LazyLogging {
)(kms => IO(kms.shutdown()))

def transactor(ssm: AWSSimpleSystemsManagement, db: Config.Database): Resource[IO, Transactor[IO]] = for {
username <- Resource.eval(resolve(blocker, ssm, db.username))
password <- Resource.eval(resolve(blocker, ssm, db.password))
jdbcUrl <- Resource.eval(resolve(blocker, ssm, db.jdbcUrl))
username <- Resource.eval(resolve(ssm, db.username))
password <- Resource.eval(resolve(ssm, db.password))
jdbcUrl <- Resource.eval(resolve(ssm, db.jdbcUrl))
connectEC <- ExecutionContexts.fixedThreadPool[IO](32)
xa <- HikariTransactor.newHikariTransactor[IO](
blocker = blocker,
connectEC = connectEC,
driverClassName = "org.postgresql.Driver",
pass = password,
Expand All @@ -73,8 +64,7 @@ object Resources extends LazyLogging {
case Config.Literal(value) =>
IO.pure(value)
case Config.SsmParam(value, encrypted) =>
blocker
.blockOn(IO(ssm.getParameter(new GetParameterRequest().withName(value).withWithDecryption(encrypted))))
IO.blocking(ssm.getParameter(new GetParameterRequest().withName(value).withWithDecryption(encrypted)))
.map(_.getParameter.getValue)
.attempt
.map {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.narrative.connectors.facebook

import cats.effect.{IO, IOApp, Resource}
import com.comcast.ip4s.{Host, Port}
import com.typesafe.scalalogging.LazyLogging
import io.narrative.connectors.facebook.routes.Logging
import io.narrative.connectors.facebook.routes.profiles.ProfileRoutes
Expand All @@ -15,7 +16,7 @@ import io.narrative.connectors.facebook.services.{
}
import io.narrative.connectors.facebook.stores.ProfileStore
import org.http4s.{HttpApp, Uri}
import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.ember.server.EmberServerBuilder
import org.http4s.server.Router
import org.http4s.server.middleware.CORS

Expand All @@ -25,10 +26,20 @@ object Server extends IOApp.Simple with LazyLogging {
config <- Resource.eval(Config())
resources <- Resources(config)
routes <- Resource.eval(router(config, resources))
server <- BlazeServerBuilder[IO](resources.serverEC)
.bindHttp(config.server.port.value.toInt, "0.0.0.0")
server <- EmberServerBuilder
.default[IO]
.withHost(
Host
.fromString("0.0.0.0")
.getOrElse(throw new RuntimeException("Programming error: host 0.0.0.0 is not valid"))
)
.withPort(
Port
.fromString(config.server.port.value)
.getOrElse(throw new RuntimeException(s"Programming error: port ${config.server.port.value} is not valid"))
)
.withHttpApp(routes)
.resource
.build
} yield server

server.use(_ => IO.never).void
Expand All @@ -41,11 +52,11 @@ object Server extends IOApp.Simple with LazyLogging {
kmsKeyId <- resources.resolve(config.kms.tokenEncryptionKeyId).map(KmsKeyId.apply)
apiBaseUri <- resources.resolve(config.narrativeApi.baseUri).map(Uri.unsafeFromString)
apiClient = new ApiClient(baseUri = apiBaseUri, client = resources.client)
fbClient = new FacebookClient(FacebookApp(appId, appSecret), blocker = resources.blocker)
fbClient = new FacebookClient(FacebookApp(appId, appSecret))
profileService = new ProfileService(
apiClient,
fbClient,
new TokenEncryptionService(resources.blocker, kmsKeyId, resources.kms),
new TokenEncryptionService(kmsKeyId, resources.kms),
ProfileStore(resources.xa)
)
http = CORS.policy.withAllowCredentials(false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.narrative.connectors.facebook.routes

import cats.data.{Kleisli, OptionT}
import cats.effect.IO
import cats.syntax.applicativeError._
import com.typesafe.scalalogging.LazyLogging
import io.narrative.connectors.facebook.services.BearerToken
import org.http4s.client.UnexpectedStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ object Logging extends LazyLogging {
resp <- service(req)
_ <- resp.status.code match {
case code if code >= 400 =>
org.http4s.internal.Logger.logMessageWithBodyText[IO, Response[IO]](resp)(
org.http4s.internal.Logger.logMessageWithBodyText[IO](resp)(
logHeaders = true,
logBodyText = truncateBody(32768) _
)(logWarn)
Expand All @@ -40,5 +40,5 @@ object Logging extends LazyLogging {
}

private def truncateBody(maxBytes: Int)(bytes: fs2.Stream[IO, Byte]): Option[IO[String]] =
bytes.take(maxBytes.toLong).through(fs2.text.utf8Decode).compile.last.map(_.getOrElse("")).some
bytes.take(maxBytes.toLong).through(fs2.text.utf8.decode).compile.last.map(_.getOrElse("")).some
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import org.http4s._
import org.http4s.circe.CirceEntityCodec._
import org.http4s.dsl.io._

class ProfileRoutes(service: ProfileService.Ops[IO])(implicit
contextShift: ContextShift[IO]
) extends LazyLogging {
class ProfileRoutes(service: ProfileService.Ops[IO]) extends LazyLogging {

val routes: HttpRoutes[IO] = Auth.auth {
case GET -> Root as auth => profiles(auth)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.http4s._
import org.http4s.circe.CirceEntityCodec._
import org.http4s.dsl.io._

class TokenRoutes(service: ProfileService.Ops[IO])(implicit contextShift: ContextShift[IO]) extends LazyLogging {
class TokenRoutes(service: ProfileService.Ops[IO]) extends LazyLogging {

val routes: HttpRoutes[IO] = Auth.noauth { case req @ POST -> Root / "metadata" =>
tokenMeta(req)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package io.narrative.connectors.facebook.services

import cats.{Eq, Show}
import cats.effect.IO
import cats.syntax.applicativeError._
import cats.syntax.show._
import cats.implicits._
import io.circe.{Decoder, Encoder}
import io.circe.generic.extras.semiauto.{deriveConfiguredDecoder, deriveConfiguredEncoder}
import org.http4s.circe.CirceEntityCodec._
Expand All @@ -13,7 +12,7 @@ import org.http4s.headers.Authorization
import io.narrative.connectors.facebook.domain.Profile

/** todo(mbabic) scaladocs */
class ApiClient(baseUri: Uri, client: Client[IO])(implicit contextShift: ContextShift[IO]) extends ApiClient.Ops[IO] {
class ApiClient(baseUri: Uri, client: Client[IO]) extends ApiClient.Ops[IO] {
import ApiClient._

override def company(auth: BearerToken): IO[ApiCompany] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package io.narrative.connectors.facebook.services

import cats.{Eq, Show}
import cats.effect.IO
import cats.syntax.applicativeError._
import cats.syntax.option._
import cats.implicits._
import com.typesafe.scalalogging.LazyLogging
import fs2.Stream
import io.circe.{Decoder, Encoder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package io.narrative.connectors.facebook.services

import cats.data.NonEmptyList
import cats.effect.IO
import cats.instances.list._
import cats.syntax.show._
import cats.syntax.traverse._
import cats.implicits._
import com.facebook.ads.{sdk => fb}
import com.google.gson.{JsonArray, JsonObject, JsonPrimitive}
import com.typesafe.scalalogging.LazyLogging
Expand All @@ -17,14 +15,9 @@ import java.time.Instant
import scala.jdk.CollectionConverters._
import scala.concurrent.duration._
import scala.util.control.NoStackTrace
import cats.effect.Temporal

/** A Facebook API wrapper. */
class FacebookClient(app: FacebookApp, blocker: Blocker)(implicit
cs: ContextShift[IO],
timer: Temporal[IO]
) extends FacebookClient.Ops[IO]
with LazyLogging {
class FacebookClient(app: FacebookApp) extends FacebookClient.Ops[IO] with LazyLogging {
import FacebookClient._

// Facebook has special support for constructing tokens that allow an app to perform actions by concatenating the
Expand Down Expand Up @@ -239,16 +232,14 @@ class FacebookClient(app: FacebookApp, blocker: Blocker)(implicit

private def runIO[A](apiCall: => A): IO[A] =
retryingOnSomeErrors(retryPolicy, shouldRetry, logError) {
blocker.blockOn(
IO(apiCall)
.timeout(HttpTimeout)
.handleErrorWith {
// https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling/
case e: fb.APIException.FailedRequestException if getErrorCode(e).contains(190) =>
IO.raiseError(InvalidAccessToken)
case t => IO.raiseError(t)
}
)
IO.blocking(apiCall)
.timeout(HttpTimeout)
.handleErrorWith {
// https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling/
case e: fb.APIException.FailedRequestException if getErrorCode(e).contains(190) =>
IO.raiseError(InvalidAccessToken)
case t => IO.raiseError(t)
}
}
}

Expand Down Expand Up @@ -373,10 +364,10 @@ object FacebookClient extends LazyLogging {
payload
}

private def shouldRetry(t: Throwable): Boolean = t match {
private def shouldRetry(t: Throwable): IO[Boolean] = t match {
case failedRequest: fb.APIException.FailedRequestException =>
getErrorCode(failedRequest).exists(RetryableErrorCodes.contains)
case _ => false
getErrorCode(failedRequest).exists(RetryableErrorCodes.contains).pure[IO]
case _ => false.pure[IO]
}

private def logError(t: Throwable, retryDetails: RetryDetails): IO[Unit] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import io.narrative.connectors.facebook.domain.Token
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets

class TokenEncryptionService(blocker: Blocker, keyId: KmsKeyId, kms: AWSKMS)(implicit contextShift: ContextShift[IO])
extends TokenEncryptionService.Ops[IO] {
class TokenEncryptionService(keyId: KmsKeyId, kms: AWSKMS) extends TokenEncryptionService.Ops[IO] {
override def decrypt(token: Token.Encrypted): IO[FacebookToken] = {
val req = new DecryptRequest().withKeyId(keyId.value).withCiphertextBlob(ByteBuffer.wrap(token.value))
runIO(new String(kms.decrypt(req).getPlaintext.array(), StandardCharsets.UTF_8)).map(FacebookToken.apply)
Expand All @@ -22,7 +21,7 @@ class TokenEncryptionService(blocker: Blocker, keyId: KmsKeyId, kms: AWSKMS)(imp
runIO(kms.encrypt(req).getCiphertextBlob.array()).map(Token.Encrypted.apply)
}

private def runIO[A](f: => A): IO[A] = blocker.blockOn(IO(f))
private def runIO[A](f: => A): IO[A] = IO.blocking(f)
}

object TokenEncryptionService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import cats.syntax.functor._
import doobie.ConnectionIO
import doobie.implicits._
import doobie.postgres.implicits._
import doobie.implicits.legacy.instant._
import doobie.Fragments.set
import doobie.util.transactor.Transactor
import io.circe.syntax._
Expand Down
Loading

0 comments on commit 683a6e2

Please sign in to comment.