Skip to content

Commit 1cb5d1f

Browse files
committed
chore: Made inline usage in each request to prevent inline function used on BBBClient.execute() to improve testability
1 parent e22edb4 commit 1cb5d1f

File tree

48 files changed

+381
-117
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+381
-117
lines changed

src/main/kotlin/dev/imanity/bbbapi/BBBClient.kt

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ import io.ktor.utils.io.core.*
1212
import kotlinx.coroutines.delay
1313
import kotlinx.serialization.json.Json
1414

15-
class BBBClient(val token: Token): Closeable {
15+
class BBBClient(val token: Token) : Closeable {
1616

17-
val throttler = Throttler()
18-
val httpClient = HttpClient {
17+
private val throttler = Throttler()
18+
private val httpClient = HttpClient {
1919
install(ContentNegotiation) {
2020
json(Json {
2121
ignoreUnknownKeys = true
2222
})
23-
//ignoreUnknownKeys = true
2423
}
2524
}
2625

27-
suspend inline fun <reified T : Any> execute(request: Request<T>, wait: Boolean = true): Response<T> {
26+
suspend fun <T : Any> execute(request: Request<T>, wait: Boolean = true): Response<T> {
2827
while (wait) {
2928
val stall = throttler.stall(request.method)
3029
if (stall <= 0) {
@@ -49,88 +48,60 @@ class BBBClient(val token: Token): Closeable {
4948
return this.executeRequest(request)
5049
}
5150

52-
suspend inline fun <reified T : Any> executeRequest(request: Request<T>): Response<T> {
53-
return when (request.method) {
51+
private suspend fun <T : Any> executeRequest(request: Request<T>) = kotlin.runCatching {
52+
val httpResponse = when (request.method) {
5453
Method.GET -> get(request)
5554
Method.POST -> post(request, request.body!!)
5655
Method.DELETE -> delete(request)
5756
Method.PATCH -> patch(request, request.body!!)
5857
}
59-
}
60-
61-
suspend inline fun <reified T> get(request: Request<T>): Response<T> {
62-
return try {
63-
val response = httpClient.get(request.url) {
64-
headers {
65-
append("Authorization", token.urlString)
66-
}
67-
}
6858

69-
decode(response)
70-
} catch (ex: Exception) {
71-
Response(ex)
72-
}
59+
request.decode(httpResponse)
60+
}.getOrElse {
61+
Response(Type.EXCEPTION, null, null, it, 0)
7362
}
7463

75-
suspend inline fun <reified T> post(request: Request<T>, body: Any): Response<T> {
76-
return try {
77-
val response = httpClient.post(request.url) {
78-
headers {
79-
append("Authorization", token.urlString)
80-
append("Content-Type", "application/json")
81-
}
82-
setBody(body)
83-
}
84-
85-
decode(response)
86-
} catch (ex: Exception) {
87-
Response(ex)
64+
private suspend fun get(request: Request<*>) = httpClient.get(request.url) {
65+
headers {
66+
append("Authorization", token.urlString)
8867
}
8968
}
9069

91-
suspend inline fun <reified T> delete(request: Request<T>): Response<T> {
92-
return try {
93-
val response = httpClient.delete(request.url) {
94-
headers {
95-
append("Authorization", token.urlString)
96-
}
97-
}
98-
99-
decode(response)
100-
} catch (ex: Exception) {
101-
Response(ex)
70+
private suspend fun post(request: Request<*>, body: Any) = httpClient.post(request.url) {
71+
headers {
72+
append("Authorization", token.urlString)
73+
append("Content-Type", "application/json")
10274
}
75+
setBody(body)
10376
}
10477

105-
suspend inline fun <reified T> patch(request: Request<T>, body: Any): Response<T> {
106-
return try {
107-
val response = httpClient.patch(request.url) {
108-
headers {
109-
append("Authorization", token.urlString)
110-
append("Content-Type", "application/json")
111-
}
112-
setBody(body)
113-
}
114-
115-
decode(response)
116-
} catch (ex: Exception) {
117-
Response(ex)
78+
private suspend fun delete(request: Request<*>) = httpClient.delete(request.url) {
79+
headers {
80+
append("Authorization", token.urlString)
11881
}
11982
}
12083

121-
suspend inline fun <reified T> decode(response: HttpResponse): Response<T> {
122-
val body = response.body<ResponseBody<T>>()
123-
return if (response.headers.contains("Retry-After")) {
124-
Response(response.headers["Retry-After"]!!.toLong())
125-
} else if (body.result == "error") {
126-
Response(body.error!!)
127-
} else {
128-
Response(body.data!!)
84+
private suspend fun patch(request: Request<*>, body: Any) = httpClient.patch(request.url) {
85+
headers {
86+
append("Authorization", token.urlString)
87+
append("Content-Type", "application/json")
12988
}
89+
setBody(body)
13090
}
13191

13292
override fun close() {
13393
httpClient.close()
13494
}
13595

96+
}
97+
98+
suspend inline fun <reified T : Any> decodeResponse(response: HttpResponse): Response<T> {
99+
val body = response.body<ResponseBody<T>>()
100+
return if (response.headers.contains("Retry-After")) {
101+
Response(response.headers["Retry-After"]!!.toLong())
102+
} else if (body.result == "error") {
103+
Response(body.error!!)
104+
} else {
105+
Response(body.data!!)
106+
}
136107
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package dev.imanity.bbbapi.request
22

3-
open class Request<T>(urlPath: String,
3+
import io.ktor.client.statement.*
4+
5+
abstract class Request<T>(urlPath: String,
46
val method: Method,
57
val body: Any?) {
68
val url = "https://api.builtbybit.com/v1/$urlPath"
9+
10+
abstract suspend fun decode(httpResponse: HttpResponse): Response<T>
11+
712
}

src/main/kotlin/dev/imanity/bbbapi/request/Response.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ package dev.imanity.bbbapi.request
22

33
import java.lang.Exception
44

5-
data class Response<T>(
5+
data class Response<out T>(
66
val type: Type,
77
val value: T?,
88
val error: Error?,
9-
val exception: Exception?,
9+
val exception: Throwable?,
1010
val rateLimitTime: Long
1111
) {
1212
constructor(error: Error) : this(Type.ERROR, null, error, null, 0)
13-
constructor(exception: Exception) : this(Type.EXCEPTION, null, null, exception, 0)
13+
constructor(exception: Throwable) : this(Type.EXCEPTION, null, null, exception, 0)
1414
constructor(rateLimitTime: Long) : this(Type.RATE_LIMITED, null, null, null, rateLimitTime)
1515
constructor(value: T) : this(Type.SUCCESS, value, null, null, 0)
1616
}

src/main/kotlin/dev/imanity/bbbapi/request/impl/HealthRequest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@ package dev.imanity.bbbapi.request.impl
22

33
import dev.imanity.bbbapi.request.Method
44
import dev.imanity.bbbapi.request.Request
5+
import dev.imanity.bbbapi.request.Response
6+
import io.ktor.client.statement.*
57

68
class HealthRequest: Request<String>("health", Method.GET, null) {
9+
override suspend fun decode(httpResponse: HttpResponse): Response<String> {
10+
return dev.imanity.bbbapi.decodeResponse(httpResponse)
11+
}
12+
713
override fun equals(other: Any?): Boolean {
814
if (this === other) return true
915
if (javaClass != other?.javaClass) return false
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package dev.imanity.bbbapi.request.impl.alert
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.model.Alert
45
import dev.imanity.bbbapi.model.sort.SortOptions
56
import dev.imanity.bbbapi.request.Method
67
import dev.imanity.bbbapi.request.Request
8+
import dev.imanity.bbbapi.request.Response
9+
import io.ktor.client.statement.*
710

811
data class ListUnreadAlertsRequest(
912
val sortOptions: SortOptions
1013
): Request<Array<Alert>>(
1114
"alerts/alerts${sortOptions}",
1215
Method.GET,
1316
null
14-
)
17+
) {
18+
override suspend fun decode(httpResponse: HttpResponse): Response<Array<Alert>> {
19+
return decodeResponse(httpResponse)
20+
}
21+
}

src/main/kotlin/dev/imanity/bbbapi/request/impl/alert/MarkUnreadAlertsAsReadRequest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package dev.imanity.bbbapi.request.impl.alert
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.request.Method
45
import dev.imanity.bbbapi.request.Request
6+
import dev.imanity.bbbapi.request.Response
7+
import io.ktor.client.statement.*
58

69
data class MarkUnreadAlertsAsReadRequest(
710
val read: Boolean
@@ -11,4 +14,8 @@ data class MarkUnreadAlertsAsReadRequest(
1114
mapOf(
1215
"read" to read
1316
)
14-
)
17+
) {
18+
override suspend fun decode(httpResponse: HttpResponse): Response<Unit> {
19+
return decodeResponse(httpResponse)
20+
}
21+
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package dev.imanity.bbbapi.request.impl.conversation
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.model.Conversation
45
import dev.imanity.bbbapi.model.sort.SortOptions
56
import dev.imanity.bbbapi.request.Method
67
import dev.imanity.bbbapi.request.Request
8+
import dev.imanity.bbbapi.request.Response
9+
import io.ktor.client.statement.*
710

811
data class ListUnreadConversationsRequest(
912
val sortOptions: SortOptions
1013
): Request<Array<Conversation>>(
1114
"conversations/conversations${sortOptions}",
1215
Method.GET,
1316
null
14-
)
17+
) {
18+
override suspend fun decode(httpResponse: HttpResponse): Response<Array<Conversation>> {
19+
return decodeResponse(httpResponse)
20+
}
21+
}

src/main/kotlin/dev/imanity/bbbapi/request/impl/conversation/StartConversationRequest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package dev.imanity.bbbapi.request.impl.conversation
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.request.Method
45
import dev.imanity.bbbapi.request.Request
6+
import dev.imanity.bbbapi.request.Response
7+
import io.ktor.client.statement.*
58

69
data class StartConversationRequest(
710
val userIds: Array<Int>,
@@ -35,4 +38,8 @@ data class StartConversationRequest(
3538
result = 31 * result + message.hashCode()
3639
return result
3740
}
41+
42+
override suspend fun decode(httpResponse: HttpResponse): Response<Int> {
43+
return decodeResponse(httpResponse)
44+
}
3845
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package dev.imanity.bbbapi.request.impl.conversation.reply
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.model.Reply
45
import dev.imanity.bbbapi.model.sort.SortOptions
56
import dev.imanity.bbbapi.request.Method
67
import dev.imanity.bbbapi.request.Request
8+
import dev.imanity.bbbapi.request.Response
9+
import io.ktor.client.statement.*
710

811
data class ListUnreadConversationRepliesRequest(
912
val conversationId: Int,
@@ -12,4 +15,8 @@ data class ListUnreadConversationRepliesRequest(
1215
"conversations/$conversationId/replies${sortOptions}",
1316
Method.GET,
1417
null
15-
)
18+
) {
19+
override suspend fun decode(httpResponse: HttpResponse): Response<Array<Reply>> {
20+
return decodeResponse(httpResponse)
21+
}
22+
}

src/main/kotlin/dev/imanity/bbbapi/request/impl/conversation/reply/ReplyToUnreadConversationRequest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package dev.imanity.bbbapi.request.impl.conversation.reply
22

3+
import dev.imanity.bbbapi.decodeResponse
34
import dev.imanity.bbbapi.request.Method
45
import dev.imanity.bbbapi.request.Request
6+
import dev.imanity.bbbapi.request.Response
7+
import io.ktor.client.statement.*
58

69
data class ReplyToUnreadConversationRequest(
710
val conversationId: Int,
@@ -12,4 +15,8 @@ data class ReplyToUnreadConversationRequest(
1215
mapOf(
1316
"message" to message,
1417
),
15-
)
18+
) {
19+
override suspend fun decode(httpResponse: HttpResponse): Response<Int> {
20+
return decodeResponse(httpResponse)
21+
}
22+
}

0 commit comments

Comments
 (0)