Skip to content

Commit

Permalink
add semaphore to throttle http calls
Browse files Browse the repository at this point in the history
  • Loading branch information
nylonee committed Nov 13, 2023
1 parent c7e0c7b commit 9b8007e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
31 changes: 17 additions & 14 deletions src/main/scala/Server.scala
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@

import cats.effect._
import cats.effect.std.Semaphore
import configuration.{Configuration, ConfigurationUtils, SystemPropertyReader}
import org.http4s.ember.client.EmberClientBuilder
import utils.HttpClient

object Server extends IOApp {
def run(args: List[String]): IO[ExitCode] = {
val configReader = SystemPropertyReader
val httpClient = new HttpClient()
val configIO: IO[Configuration] = ConfigurationUtils.create(configReader, httpClient)
val memoizedConfigIO: IO[IO[Configuration]] = configIO.memoize

def periodicTask(configIO: IO[Configuration]): IO[Unit] =
for {
config <- configIO
_ <- WatchlistSync.run(config, httpClient)
_ <- IO.sleep(config.refreshInterval)
_ <- periodicTask(configIO)
} yield ()
val maxConcurrentOutgoingRequests = 1

for {
getConfig <- memoizedConfigIO
result <- periodicTask(getConfig).foreverM.as(ExitCode.Success)
semaphore <- Semaphore[IO](maxConcurrentOutgoingRequests)
configReader = SystemPropertyReader
clientResource = EmberClientBuilder.default[IO].build
httpClient = new HttpClient(clientResource, semaphore)
memoizedConfigIo <- ConfigurationUtils.create(configReader, httpClient).memoize
result <- periodicTask(memoizedConfigIo, httpClient).foreverM.as(ExitCode.Success)
} yield result
}

private def periodicTask(configIO: IO[Configuration], httpClient: HttpClient): IO[Unit] =
for {
config <- configIO
_ <- WatchlistSync.run(config, httpClient)
_ <- IO.sleep(config.refreshInterval)
_ <- periodicTask(configIO, httpClient)
} yield ()
}
18 changes: 9 additions & 9 deletions src/main/scala/utils/HttpClient.scala
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package utils

import cats.effect.IO
import cats.effect.{IO, Resource}
import io.circe.Json
import org.http4s.{Header, Method, Request, Uri}
import org.http4s.ember.client.EmberClientBuilder
import org.typelevel.ci.CIString
import org.http4s.circe._
import org.http4s.client.Client
import org.slf4j.LoggerFactory
import cats.effect.std.Semaphore

class HttpClient {
class HttpClient(http4sClient: Resource[IO, Client[IO]], semaphore: Semaphore[IO]) {
private val logger = LoggerFactory.getLogger(getClass)

private val clientResource = EmberClientBuilder
.default[IO]
.build

def httpRequest(method: Method, url: Uri, apiKey: Option[String] = None, payload: Option[Json] = None): IO[Either[Throwable, Json]] = {
val baseRequest = Request[IO](method = method, uri = url).withHeaders(Header.Raw(CIString("Accept"), "application/json"))
val requestWithApiKey = apiKey.fold(baseRequest)(key => baseRequest.withHeaders(Header.Raw(CIString("X-Api-Key"), key)))
val requestWithPayload = payload.fold(requestWithApiKey)(p => requestWithApiKey.withEntity(p))

logger.info(s"Thread: ${Thread.currentThread()}")
clientResource.use(_.expect[Json](requestWithPayload).attempt)

semaphore.permit.use { _ =>
http4sClient.use(_.expect[Json](requestWithPayload).attempt)
}
}
}
}

0 comments on commit 9b8007e

Please sign in to comment.