我正在构建一个库,Sttp.client3
用作可以通过同步和异步环境实现的基础,我使用 zio-http 作为我的服务和 sttp-client 与其他服务交互。
我有以下特点:
trait CoingeckoApiClient extends CoingeckoClient {
.....
override def ping: Either[CoingeckoApiError, PingResponse] =
get[PingResponse](endpoint = "ping", QueryParams())
def get[T](endpoint: String, queryParams: QueryParams)(
using Format[T]
): Either[CoingeckoApiError, T]
}
和 API
class CoingeckoApi[F[_], P](using val backend: SttpBackend[F, P]) {
def get(endpoint: String, params: QueryParams): F[Response[Either[String, String]]] = {
val apiUrl = s"${CoingeckoApi.baseUrl}/$endpoint"
basicRequest
.get(
uri"$apiUrl"
.withParams(params)
)
.send(backend)
}
}
一个同步的实现如下:
class CoingeckoApiBasic(api: CoingeckoApi[Identity, Any]) extends CoingeckoApiClient {
def get[T](endpoint: String, queryParams: QueryParams)(using Format[T]): Either[CoingeckoApiError, T] =
api.get(endpoint, queryParams).body match {
case Left(json) =>
Json.parse(json).validate[CoingeckoApiError] match {
case JsSuccess(value, _) => Left(value)
case JsError(errors) =>
Left(CoingeckoApiError.internalApiError(Some("Unknown Api Error")))
}
case Right(json) =>
Json.parse(json).validate[T] match {
case JsSuccess(value, _) =>
Right(value)
case JsError(errors) =>
Left(
CoingeckoApiError
.internalApiError(Some(s"Invalid Response for $endpoint"))
)
}
}
}
所以我希望用 ZIO 提供一个异步实现
class CoingeckoApiZIO(api: CoingeckoApi[UIO, Any]) extends CoingeckoApiClient {
def get[T](endpoint: String, queryParams: QueryParams)(using Format[T]): Either[CoingeckoApiError, T] =
Runtime.unsafeRun {
api.get(endpoint, queryParams).map(r => r.body match {
case Left(json) =>
Json.parse(json).validate[CoingeckoApiError] match {
case JsSuccess(value, _) => Left(value)
case JsError(errors) =>
Left(CoingeckoApiError.internalApiError(Some("Unknown Api Error")))
}
case Right(json) =>
Json.parse(json).validate[T] match {
case JsSuccess(value, _) =>
Right(value)
case JsError(errors) =>
Left(
CoingeckoApiError
.internalApiError(Some(s"Invalid Response for $endpoint"))
)
}
})
}
}
这是否意味着,我需要在这个级别提供一个运行时?在我看来,提供一个足够灵活以供 ZIO、Future 和其他人使用的 API 似乎有点困难,而且我可能在这里遗漏了一些重要的东西。
我可能需要更改签名class CoingeckoApi[F[_], P]
以支持环境?
我正在尝试遵循可以使用多个后端的 sttp 的步骤,但它似乎有点难以扩展,或者我需要重写我的 API。