Skip to content

Commit

Permalink
Introduce unary callable in http common (#822)
Browse files Browse the repository at this point in the history
ashdavies authored Jan 30, 2024
1 parent cb739dd commit 9281e3e
Showing 5 changed files with 72 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -19,14 +19,14 @@ private const val DEFAULT_PAGE_SIZE = 10
@MultipleReferenceWarning
internal fun rememberEventPager(
eventsQueries: EventsQueries = rememberPlaygroundDatabase().eventsQueries,
eventsService: EventsService = EventsService(LocalHttpClient.current),
eventsCallable: GetEventsCallable = GetEventsCallable(LocalHttpClient.current),
initialKey: String = todayAsString(),
pageSize: Int = DEFAULT_PAGE_SIZE,
): Pager<String, Event> = remember(eventsQueries, eventsService) {
): Pager<String, Event> = remember(eventsQueries, eventsCallable) {
Pager(
config = PagingConfig(pageSize),
initialKey = initialKey,
remoteMediator = EventsRemoteMediator(eventsQueries, eventsService),
remoteMediator = EventsRemoteMediator(eventsQueries, eventsCallable),
pagingSourceFactory = { EventsPagingSource(eventsQueries) },
)
}
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import io.ashdavies.playground.Event as DatabaseEvent
@OptIn(ExperimentalPagingApi::class)
internal class EventsRemoteMediator(
private val eventsQueries: EventsQueries,
private val eventsService: EventsService,
private val eventsCallable: GetEventsCallable,
) : RemoteMediator<String, DatabaseEvent>() {

override suspend fun load(
@@ -27,10 +27,10 @@ internal class EventsRemoteMediator(
}

val result: List<ApiEvent> = try {
eventsService.getEvents(loadKey)
eventsCallable(GetEventsRequest(loadKey))
} catch (exception: SocketTimeoutException) {
return MediatorResult.Error(exception)
} catch (exception: ErrorResponse) {
} catch (exception: GetEventsError) {
return MediatorResult.Error(exception)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.ashdavies.playground.events

import io.ashdavies.http.DefaultHttpClient
import io.ashdavies.http.UnaryCallable
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.plugins.ClientRequestException
import io.ktor.client.plugins.DefaultRequest
import io.ktor.client.plugins.HttpCallValidator
import io.ktor.client.request.get
import kotlinx.serialization.Serializable
import io.ashdavies.http.common.models.Event as ApiEvent

private const val NETWORK_PAGE_SIZE = 100
private const val PLAYGROUND_API_HOST = "playground.ashdavies.dev"

@Serializable
internal data class GetEventsRequest(
val startAt: String? = null,
val limit: Int = NETWORK_PAGE_SIZE,
)

internal typealias GetEventsResponse = List<ApiEvent>

internal class GetEventsCallable(
httpClient: HttpClient = DefaultHttpClient(),
) : UnaryCallable<GetEventsRequest, GetEventsResponse> {

private val httpClient = httpClient.config {
install(DefaultRequest) {
host = PLAYGROUND_API_HOST
}

install(HttpCallValidator) {
handleResponseExceptionWithRequest { exception, _ ->
if (exception is ClientRequestException) {
throw exception.response.body<GetEventsError>()
}
}
}

expectSuccess = true
}

override suspend fun invoke(request: GetEventsRequest): GetEventsResponse {
val queryAsString = buildList {
if (request.startAt != null) add("startAt=${request.startAt}")
add("limit=${request.limit}")
}.joinToString("&")

return httpClient
.get("events?$queryAsString")
.body()
}
}

@Serializable
public data class GetEventsError(
override val message: String,
val code: Int,
) : Throwable()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.ashdavies.http

public fun interface UnaryCallable<Request, Response> {
public suspend operator fun invoke(request: Request): Response
}

0 comments on commit 9281e3e

Please sign in to comment.