Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ object ArmeriaCatsBackend {
): Resource[F, Backend[F]] =
Resource.make(Sync[F].delay(apply(newClient(options), closeFactory = true)))(_.close())

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the resource is released. */
def resourceUsingClient[F[_]: Concurrent](client: WebClient): Resource[F, Backend[F]] =
Resource.make(Sync[F].delay(apply(client, closeFactory = true)))(_.close())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ object ArmeriaCatsBackend {
): Resource[F, Backend[F]] =
Resource.make(Sync[F].delay(apply(newClient(options), closeFactory = true)))(_.close())

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the resource is released. */
def resourceUsingClient[F[_]: Async](client: WebClient): Resource[F, Backend[F]] =
Resource.make(Sync[F].delay(apply(client, closeFactory = true)))(_.close())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ object ArmeriaFs2Backend {
): Resource[F, StreamBackend[F, Fs2Streams[F]]] =
Resource.make(Sync[F].delay(apply(newClient(options), closeFactory = true)))(_.close())

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the resource is released. */
def resourceUsingClient[F[_]: ConcurrentEffect](client: WebClient): Resource[F, StreamBackend[F, Fs2Streams[F]]] =
Resource.make(Sync[F].delay(apply(client, closeFactory = true)))(_.close())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ object ArmeriaFs2Backend {
Resource.make(Sync[F].delay(apply(newClient(options), closeFactory = true, dispatcher)))(_.close())
)

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the resource is released. */
def resourceUsingClient[F[_]: Async](client: WebClient): Resource[F, StreamBackend[F, Fs2Streams[F]]] =
Dispatcher
.parallel[F]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import sttp.client4.impl.monix.TaskMonadAsyncError
import sttp.client4.wrappers.FollowRedirectsBackend
import sttp.client4.{wrappers, BackendOptions, StreamBackend}
import sttp.monad.MonadAsyncError
import cats.effect.ExitCase
import cats.effect.{ExitCase, Resource}

private final class ArmeriaMonixBackend(client: WebClient, closeFactory: Boolean)(implicit scheduler: Scheduler)
extends AbstractArmeriaBackend[Task, MonixStreams](client, closeFactory, TaskMonadAsyncError) {
Expand Down Expand Up @@ -54,6 +54,21 @@ object ArmeriaMonixBackend {
): StreamBackend[Task, MonixStreams] =
apply(newClient(options), closeFactory = true)

/** @param scheduler The scheduler used for streaming request bodies. Defaults to the global scheduler. */
def resource(options: BackendOptions = BackendOptions.Default)(implicit
scheduler: Scheduler = Scheduler.global
): Resource[Task, StreamBackend[Task, MonixStreams]] =
Resource.make(Task.eval(apply(options)))(_.close())

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the resource is released.
* @param scheduler
* The scheduler used for streaming request bodies. Defaults to the global scheduler.
*/
def resourceUsingClient(client: WebClient)(implicit
scheduler: Scheduler = Scheduler.global
): Resource[Task, StreamBackend[Task, MonixStreams]] =
Resource.make(Task.eval(apply(client, closeFactory = true)))(_.close())

/** @param scheduler The scheduler used for streaming request bodies. Defaults to the global scheduler. */
def usingClient(client: WebClient)(implicit
scheduler: Scheduler = Scheduler.global
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ object ArmeriaZioBackend {
): ZIO[Scope, Throwable, StreamBackend[Task, ZioStreams]] =
ZIO.acquireRelease(apply(options))(_.close().ignore)

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the scope is closed. */
def scopedUsingClient(client: WebClient): ZIO[Scope, Throwable, StreamBackend[Task, ZioStreams]] =
ZIO.acquireRelease(
ZIO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ object ArmeriaZioBackend {
def managed(options: BackendOptions = BackendOptions.Default): TaskManaged[StreamBackend[Task, ZioStreams]] =
ZManaged.make(apply(options))(_.close().ignore)

/** Creates a backend using the given client. The client's `ClientFactory` is closed when the managed resource is
* released.
*/
def managedUsingClient(client: WebClient): TaskManaged[StreamBackend[Task, ZioStreams]] =
ZManaged.make(
ZIO
.runtime[Any]
.map(runtime => apply(runtime, client, closeFactory = true))
)(_.close().ignore)

def layer(options: BackendOptions = BackendOptions.Default): Layer[Throwable, SttpClient] =
ZLayer.fromManaged(managed(options))

Expand Down
9 changes: 9 additions & 0 deletions docs/backends/monix.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ OkHttpMonixBackend.resource().use { backend => ??? }
import okhttp3._
val okHttpClient: OkHttpClient = ???
val backend = OkHttpMonixBackend.usingClient(okHttpClient)

// or, obtain a cats-effect Resource with a custom instance of the OkHttpClient:
OkHttpMonixBackend.resourceUsingClient(okHttpClient).use { backend => ??? }
```

This backend depends on [OkHttp](http://square.github.io/okhttp/) and fully supports HTTP/2.
Expand All @@ -90,6 +93,9 @@ create client:
import monix.execution.Scheduler.Implicits.global
val backend = ArmeriaMonixBackend()

// or, if you'd like the backend to be wrapped in cats-effect Resource:
ArmeriaMonixBackend.resource().use { backend => ??? }

// You can use the default client which reuses the connection pool of ClientFactory.ofDefault()
ArmeriaMonixBackend.usingDefaultClient()
```
Expand All @@ -108,6 +114,9 @@ val client = WebClient.builder("https://my-service.com")
.build()

val backend = ArmeriaMonixBackend.usingClient(client)

// or, obtain a cats-effect Resource with a custom instance of the WebClient:
ArmeriaMonixBackend.resourceUsingClient(client).use { backend => ??? }
```

```{note}
Expand Down
2 changes: 2 additions & 0 deletions docs/backends/zio.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ The `CurlZioBackend` companion object contains methods to create the backend dir

When using constructors to express service dependencies, ZIO layers can be used to provide the `SttpBackend` instance, instead of creating one by hand. In this scenario, the lifecycle of a `SttpBackend` service is described by `ZLayer`s, which can be created using the `.layer`/`.layerUsingConfig`/... methods on `HttpClientZioBackend` / `ArmeriaZioBackend`.

A layer created with `.layerUsingClient` closes the given client when the layer is released.

The layers can be used to provide an implementation of the `SttpBackend` dependency when creating services. For example:

```scala mdoc:compile-only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ object HttpClientCatsBackend {
Resource.make(apply(dispatcher, options, customizeRequest, compressionHandlers))(_.close())
)

/** Creates a backend using the given client. The client is closed when the resource is released. */
def resourceUsingClient[F[_]: Async](
client: HttpClient,
customizeRequest: HttpRequest => HttpRequest = identity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ object HttpClientFs2Backend {
): Resource[F, WebSocketStreamBackend[F, Fs2Streams[F]]] =
Resource.make(apply(blocker, options, customizeRequest, compressionHandlers))(_.close())

/** Creates a backend using the given client. The client is closed when the resource is released. */
def resourceUsingClient[F[_]: ConcurrentEffect: ContextShift](
client: HttpClient,
blocker: Blocker,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ object HttpClientFs2Backend {
Resource.make(apply(dispatcher, options, customizeRequest, compressionHandlers))(_.close())
)

/** Creates a backend using the given client. The client is closed when the resource is released. */
def resourceUsingClient[F[_]: Async](
client: HttpClient,
customizeRequest: HttpRequest => HttpRequest = identity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ object HttpClientMonixBackend {
): Resource[Task, WebSocketStreamBackend[Task, MonixStreams]] =
Resource.make(apply(options, customizeRequest, compressionHandlers))(_.close())

/** Creates a backend using the given client. The client is closed when the resource is released. */
def resourceUsingClient(
client: HttpClient,
customizeRequest: HttpRequest => HttpRequest = identity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ object HttpClientZioBackend {
_.close().ignore
)

/** Creates a backend using the given client. The client is closed when the scope is closed. */
def scopedUsingClient(
client: HttpClient,
customizeRequest: HttpRequest => HttpRequest = identity,
Expand Down Expand Up @@ -217,18 +218,7 @@ object HttpClientZioBackend {
customizeRequest: HttpRequest => HttpRequest = identity,
compressionHandlers: CompressionHandlers[ZioStreams, ZioStreams.BinaryStream] = DefaultCompressionHandlers
): ZLayer[Any, Throwable, SttpClient] =
ZLayer.scoped(
ZIO
.acquireRelease(
ZIO.attempt(
usingClient(
client,
customizeRequest,
compressionHandlers
)
)
)(_.close().ignore)
)
ZLayer.scoped(scopedUsingClient(client, customizeRequest, compressionHandlers))

/** Create a stub backend for testing, which uses the [[Task]] response wrapper, and supports `Stream[Throwable,
* ByteBuffer]` streaming.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ object HttpClientZioBackend {
_.close().ignore
)

/** Creates a backend using the given client. The client is closed when the managed resource is released. */
def managedUsingClient(
client: HttpClient,
customizeRequest: HttpRequest => HttpRequest = identity,
compressionHandlers: CompressionHandlers[ZioStreams, ZioStreams.BinaryStream] = DefaultCompressionHandlers
): ZManaged[Any, Throwable, WebSocketStreamBackend[Task, ZioStreams]] =
ZManaged.make(
ZIO.effect(HttpClientZioBackend(client, closeClient = true, customizeRequest, compressionHandlers))
)(_.close().ignore)

def layer(
options: BackendOptions = BackendOptions.Default,
customizeRequest: HttpRequest => HttpRequest = identity,
Expand Down Expand Up @@ -203,16 +213,7 @@ object HttpClientZioBackend {
customizeRequest: HttpRequest => HttpRequest = identity,
compressionHandlers: CompressionHandlers[ZioStreams, ZioStreams.BinaryStream] = DefaultCompressionHandlers
): ZLayer[Any, Throwable, SttpClient] =
ZLayer.fromManaged(
ZManaged
.makeEffect(
usingClient(
client,
customizeRequest,
compressionHandlers
)
)(_.close().ignore)
)
ZLayer.fromManaged(managedUsingClient(client, customizeRequest, compressionHandlers))

/** Create a stub backend for testing, which uses the [[Task]] response wrapper, and supports `Stream[Throwable,
* ByteBuffer]` streaming.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ object OkHttpMonixBackend {
): Resource[Task, WebSocketStreamBackend[Task, MonixStreams]] =
Resource.make(apply(options, compressionHandlers, webSocketBufferCapacity))(_.close())

/** Creates a backend using the given client. The client is closed when the resource is released. */
def resourceUsingClient(
client: OkHttpClient,
compressionHandlers: CompressionHandlers[Any, InputStream] = DefaultCompressionHandlers,
webSocketBufferCapacity: Option[Int] = OkHttpBackend.DefaultWebSocketBufferCapacity
)(implicit
s: Scheduler = Scheduler.global
): Resource[Task, WebSocketStreamBackend[Task, MonixStreams]] =
Resource.make(
Task.eval(OkHttpMonixBackend(client, closeClient = true, compressionHandlers, webSocketBufferCapacity)(s))
)(_.close())

def usingClient(
client: OkHttpClient,
compressionHandlers: CompressionHandlers[Any, InputStream] = DefaultCompressionHandlers,
Expand Down
Loading