Skip to content

Commit 402bd1a

Browse files
committed
Add coroutine support
1 parent dd4cbf0 commit 402bd1a

6 files changed

Lines changed: 86 additions & 2 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ api.notifications().news()
8080

8181
As you can see in the example above, the individual endpoints also allow for various options.
8282

83+
##### Coroutines
84+
85+
It is also possible to execute requests in a coroutine context when using Kotlin. Use the `await` extension function on
86+
the `ProxerCall`:
87+
88+
```kt
89+
val result = api.notifications().news().build().await()
90+
```
91+
8392
### Cancelling a request
8493

8594
You might want to cancel a request, especially if using on `Android`:

gradle/dependencies.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ dependencies {
88

99
implementation "com.serjltt.moshi:moshi-lazy-adapters:$moshiLazyAdaptersVersion"
1010

11+
compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion"
12+
1113
runtimeOnly "com.squareup.okio:okio:$okioVersion"
1214

1315
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"
1416
kaptTest "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"
1517

18+
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion"
19+
1620
testImplementation "org.junit.jupiter:junit-jupiter:$junitVersion"
1721
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
1822

gradle/versions.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ext {
55
gradleVersion = "6.7.1"
66

77
kotlinVersion = "1.4.21"
8+
kotlinCoroutinesVersion = "1.4.2"
89
dokkaVersion = "1.4.20"
910

1011
jacocoVersion = "0.8.6"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package me.proxer.library
2+
3+
import kotlinx.coroutines.suspendCancellableCoroutine
4+
import kotlin.coroutines.resume
5+
import kotlin.coroutines.resumeWithException
6+
7+
suspend fun <T : Any> ProxerCall<T>.await(): T {
8+
return suspendCancellableCoroutine { continuation ->
9+
continuation.invokeOnCancellation {
10+
cancel()
11+
}
12+
13+
enqueue(
14+
{ result ->
15+
if (result != null) {
16+
continuation.resume(result)
17+
} else {
18+
continuation.resumeWithException(NullPointerException())
19+
}
20+
},
21+
{ error ->
22+
continuation.resumeWithException(error)
23+
}
24+
)
25+
}
26+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package me.proxer.library
2+
3+
import kotlinx.coroutines.CancellationException
4+
import kotlinx.coroutines.async
5+
import kotlinx.coroutines.runBlocking
6+
import okhttp3.mockwebserver.MockResponse
7+
import org.amshove.kluent.AnyException
8+
import org.amshove.kluent.coInvoking
9+
import org.amshove.kluent.shouldBe
10+
import org.amshove.kluent.shouldBeEqualTo
11+
import org.amshove.kluent.shouldNotThrow
12+
import org.amshove.kluent.shouldThrow
13+
import org.amshove.kluent.with
14+
import org.junit.jupiter.api.Test
15+
16+
class KotlinExtensionsKtTest : ProxerTest() {
17+
18+
@Test
19+
fun testAwait(): Unit = runBlocking {
20+
server.enqueue(MockResponse().setBody(fromResource("news.json")))
21+
22+
coInvoking { api.notifications.news().build().await() } shouldNotThrow AnyException
23+
}
24+
25+
@Test
26+
fun testAwaitWithError(): Unit = runBlocking {
27+
server.enqueue(MockResponse().setBody(fromResource("news.json")).setResponseCode(404))
28+
29+
coInvoking { api.notifications.news().build().await() } shouldThrow ProxerException::class with
30+
{ errorType shouldBe ProxerException.ErrorType.IO }
31+
}
32+
33+
@Test
34+
fun testCancel(): Unit = runBlocking {
35+
server.enqueue(MockResponse().setBody(fromResource("news.json")))
36+
37+
with(async { api.notifications.news().build().await() }) {
38+
cancel()
39+
40+
coInvoking { await() } shouldThrow CancellationException::class
41+
}
42+
43+
server.requestCount shouldBeEqualTo 0
44+
}
45+
}

library/src/test/kotlin/me/proxer/library/ProxerTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import okhttp3.tls.internal.TlsUtil
77
import org.junit.jupiter.api.AfterEach
88
import org.junit.jupiter.api.BeforeEach
99
import java.util.concurrent.TimeUnit
10-
import javax.net.ssl.HostnameVerifier
1110

1211
/**
1312
* Base class for all integration tests. It provides a ready to use [MockWebServer],
@@ -24,7 +23,7 @@ abstract class ProxerTest {
2423

2524
protected val client: OkHttpClient = OkHttpClient.Builder()
2625
.addInterceptor(MockWebServerUrlRewriteInterceptor(server))
27-
.hostnameVerifier(HostnameVerifier { _, _ -> true })
26+
.hostnameVerifier { _, _ -> true }
2827
.sslSocketFactory(tls.sslSocketFactory(), tls.trustManager)
2928
.connectTimeout(500, TimeUnit.MILLISECONDS)
3029
.writeTimeout(500, TimeUnit.MILLISECONDS)

0 commit comments

Comments
 (0)