From 0673b0040a9aa01d27a631151eb067002e98dea7 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Tue, 9 Oct 2018 19:50:08 -0300 Subject: [PATCH 01/10] adding retrofit adapter for arrow --- .../build.gradle | 21 +++++++ .../gradle.properties | 4 ++ .../Async2CallAdapterFactory.kt | 38 ++++++++++++ .../CallK.kt | 33 ++++++++++ .../CallKind2CallAdapter.kt | 11 ++++ .../IO2CallAdapter.kt | 12 ++++ .../ResponseCallback.kt | 28 +++++++++ .../retrofit/adapter/ApiClientTest.kt | 13 ++++ .../adapter/Async2CallAdapterFactoryTest.kt | 50 +++++++++++++++ .../retrofit/adapter/ProcCallBackTest.kt | 61 +++++++++++++++++++ .../retrofit/adapter/retrofit/Retrofit.kt | 18 ++++++ settings.gradle | 4 ++ 12 files changed, 293 insertions(+) create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/build.gradle create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/gradle.properties create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle new file mode 100644 index 00000000000..b779e459a2a --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle @@ -0,0 +1,21 @@ +dependencies { + def retrofitVersion = "2.4.0" + + compile project(':arrow-effects') + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" + compile project(':arrow-annotations') + compile "com.squareup.retrofit2:retrofit:2.4.0" + kapt project(':arrow-annotations-processor') + kaptTest project(':arrow-annotations-processor') + compileOnly project(':arrow-annotations-processor') + testCompileOnly project(':arrow-annotations-processor') + testCompile "io.kotlintest:kotlintest:$kotlinTestVersion" + testCompile project(':arrow-test') + testCompile "com.squareup.retrofit2:converter-gson:${retrofitVersion}" + testCompile 'io.kotlintest:kotlintest-runner-junit5:3.1.10' + testCompile 'com.squareup.okhttp3:mockwebserver:3.11.0' + testCompile project(':arrow-effects-rx2') +} + +apply from: rootProject.file('gradle/gradle-mvn-push.gradle') +apply plugin: 'kotlin-kapt' \ No newline at end of file diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/gradle.properties b/modules/integrations/arrow-integrations-retrofit-adapter/gradle.properties new file mode 100644 index 00000000000..10160a6a5c7 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/gradle.properties @@ -0,0 +1,4 @@ +# Maven publishing configuration +POM_NAME=Arrow-Integrations-Retrofit-Adapter +POM_ARTIFACT_ID=arrow-integration-retrofit-adapter +POM_PACKAGING=jar diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt new file mode 100644 index 00000000000..6ae3327f8e4 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt @@ -0,0 +1,38 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import retrofit2.CallAdapter +import retrofit2.Retrofit +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +class Async2CallAdapterFactory : CallAdapter.Factory() { + + companion object { + fun create() = Async2CallAdapterFactory() + } + + override fun get(returnType: Type, annotations: Array, retrofit: Retrofit): CallAdapter<*, *>? { + val rawType = CallAdapter.Factory.getRawType(returnType) + + if (returnType !is ParameterizedType) { + val name = parseTypeName(returnType) + throw IllegalArgumentException("Return type must be parameterized as " + + "$name or $name") + } + + val effectType = CallAdapter.Factory.getParameterUpperBound(0, returnType) + + return when (rawType) { + IO::class.java -> IO2CallAdapter(effectType) + CallK::class.java -> CallKind2CallAdapter(effectType) + else -> null + } + } +} + +private fun parseTypeName(type: Type) = + type.typeName + .split(".") + .last() + diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt new file mode 100644 index 00000000000..4d145643949 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt @@ -0,0 +1,33 @@ +package arrow.integrations.retrofit.adapter + +import arrow.Kind +import arrow.effects.typeclasses.Async +import arrow.effects.typeclasses.MonadDefer +import arrow.typeclasses.MonadError +import retrofit2.Call +import retrofit2.HttpException +import retrofit2.Response + +data class CallK(val call: Call) { + fun async(async: Async): Kind = + async.async { proc -> call.enqueue(ResponseCallback(proc)) } + + fun defer(defer: MonadDefer): Kind = + defer { + handleResponse(call.execute()) + } + + fun catch(defer: MonadError): Kind = + defer.run { + catch { + handleResponse(call.execute()) + } + } +} + +private fun handleResponse(response: Response) = + if (response.isSuccessful) { + response.body() ?: throw IllegalStateException("The request returned a null body") + } else { + throw HttpException(response) + } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt new file mode 100644 index 00000000000..a13166718cf --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt @@ -0,0 +1,11 @@ +package arrow.integrations.retrofit.adapter + +import retrofit2.Call +import retrofit2.CallAdapter +import java.lang.reflect.Type + +class CallKind2CallAdapter(private val type: Type) : CallAdapter> { + override fun adapt(call: Call): CallK = CallK(call) + + override fun responseType(): Type = type +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt new file mode 100644 index 00000000000..2aafa0e93f9 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt @@ -0,0 +1,12 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import retrofit2.Call +import retrofit2.CallAdapter +import java.lang.reflect.Type + +class IO2CallAdapter(private val type: Type) : CallAdapter> { + override fun adapt(call: Call): IO = IO.async { proc -> call.enqueue(ResponseCallback(proc)) } + + override fun responseType(): Type = type +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt new file mode 100644 index 00000000000..e4912610272 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt @@ -0,0 +1,28 @@ +package arrow.integrations.retrofit.adapter + +import arrow.core.Either +import arrow.core.left +import arrow.core.right +import retrofit2.Call +import retrofit2.Callback +import retrofit2.HttpException +import retrofit2.Response + +class ResponseCallback(private val proc: (Either) -> Unit) : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val body = response.body() + if (body != null) { + proc(body.right()) + } else { + proc(IllegalStateException("The request returned a null body").left()) + } + } else { + proc(HttpException(response).left()) + } + } + + override fun onFailure(call: Call, throwable: Throwable) { + proc(throwable.left()) + } +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt new file mode 100644 index 00000000000..fd09f1c2853 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt @@ -0,0 +1,13 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import retrofit2.http.GET + +interface ApiClientTest { + + @GET("test") + fun test(): CallK + + @GET("testIO") + fun testIO(): IO +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt new file mode 100644 index 00000000000..6c6409d0fa5 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt @@ -0,0 +1,50 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import arrow.test.UnitSpec +import com.google.common.reflect.TypeToken +import io.kotlintest.KTestJUnitRunner +import io.kotlintest.shouldBe +import io.kotlintest.shouldThrow +import io.kotlintest.specs.StringSpec +import org.junit.runner.RunWith +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +private val NO_ANNOTATIONS = emptyArray() + +@RunWith(KTestJUnitRunner::class) +class Async2CallAdapterFactoryTest : UnitSpec() { + private val retrofit = Retrofit.Builder() + .baseUrl("http://localhost:1") + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(Async2CallAdapterFactory.create()) + .build() + + private val factory = Async2CallAdapterFactory.create() + + init { + "Non Async Class should return null" { + factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit) shouldBe null + } + + "Non parametrized type should throw exception" { + val exceptionList = shouldThrow { + factory.get(List::class.java, NO_ANNOTATIONS, retrofit) + } + exceptionList.message shouldBe "Return type must be parameterized as List or List" + + val exceptionIO = shouldThrow { + factory.get(IO::class.java, NO_ANNOTATIONS, retrofit) + } + exceptionIO.message shouldBe "Return type must be parameterized as IO or IO" + } + + "Should work for all types" { + factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit)!! + .responseType() shouldBe String::class.java + factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit)!! + .responseType() shouldBe String::class.java + } + } +} \ No newline at end of file diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt new file mode 100644 index 00000000000..628771ea37c --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -0,0 +1,61 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import arrow.effects.ObservableK +import arrow.effects.async +import arrow.effects.fix +import arrow.effects.monadDefer +import arrow.integrations.retrofit.adapter.retrofit.retrofit +import arrow.test.UnitSpec +import io.kotlintest.KTestJUnitRunner +import okhttp3.HttpUrl +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.Assert.assertEquals +import org.junit.runner.RunWith + +@RunWith(KTestJUnitRunner::class) +class ProcCallBackTest : UnitSpec() { + private val server = MockWebServer().apply { + enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) + enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) + enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) + start() + } + + private val baseUrl: HttpUrl = server.url("/") + + init { + + "should be able to parse answer with ForIO" { + val result = retrofit(baseUrl) + .create(ApiClientTest::class.java) + .test() + .async(IO.async()) + .fix() + .unsafeRunSync() + + assertEquals(result, "hello, world!") + } + + "should be able to parse answer with ForObservableK" { + retrofit(baseUrl) + .create(ApiClientTest::class.java) + .test() + .defer(ObservableK.monadDefer()) + .fix() + .observable + .test() + .assertValue("hello, world!") + } + + "should be able to parse answer with IO" { + val result = retrofit(baseUrl) + .create(ApiClientTest::class.java) + .testIO() + .unsafeRunSync() + + assertEquals(result, "hello, world!") + } + } +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt new file mode 100644 index 00000000000..c1a1aa672f8 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt @@ -0,0 +1,18 @@ +package arrow.integrations.retrofit.adapter.retrofit + +import arrow.integrations.retrofit.adapter.Async2CallAdapterFactory +import okhttp3.HttpUrl +import okhttp3.OkHttpClient +import retrofit2.Retrofit + +private fun provideOkHttpClient(): OkHttpClient = + OkHttpClient.Builder().build() + +private fun configRetrofit(retrofitBuilder: Retrofit.Builder) = + retrofitBuilder + .addCallAdapterFactory(Async2CallAdapterFactory.create()) + .client(provideOkHttpClient()) + +private fun getRetrofitBuilderDefaults(baseUrl: HttpUrl) = Retrofit.Builder().baseUrl(baseUrl) + +fun retrofit(baseUrl: HttpUrl): Retrofit = configRetrofit(getRetrofitBuilderDefaults(baseUrl)).build() \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 847a272e760..ade60621cbf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -60,6 +60,10 @@ include { _ 'effects-reactor' } + integrations { + _ 'integrations-retrofit-adapter' + } + folder('recursion-schemes') { _ 'recursion' } From b8330c483d8654746877c3c63f74402bc0c58f33 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Tue, 9 Oct 2018 20:24:26 -0300 Subject: [PATCH 02/10] Fixing tests --- .../build.gradle | 2 -- .../retrofit/adapter/ApiClientTest.kt | 5 ++-- .../adapter/Async2CallAdapterFactoryTest.kt | 13 ++++------ .../retrofit/adapter/ProcCallBackTest.kt | 24 +++++++++---------- .../retrofit/adapter/mock/ResponseMock.kt | 3 +++ .../retrofit/adapter/retrofit/Retrofit.kt | 2 ++ 6 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle index b779e459a2a..0dc0dbc19f4 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle +++ b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle @@ -9,10 +9,8 @@ dependencies { kaptTest project(':arrow-annotations-processor') compileOnly project(':arrow-annotations-processor') testCompileOnly project(':arrow-annotations-processor') - testCompile "io.kotlintest:kotlintest:$kotlinTestVersion" testCompile project(':arrow-test') testCompile "com.squareup.retrofit2:converter-gson:${retrofitVersion}" - testCompile 'io.kotlintest:kotlintest-runner-junit5:3.1.10' testCompile 'com.squareup.okhttp3:mockwebserver:3.11.0' testCompile project(':arrow-effects-rx2') } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt index fd09f1c2853..7e8e9bf3869 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt @@ -1,13 +1,14 @@ package arrow.integrations.retrofit.adapter import arrow.effects.IO +import arrow.integrations.retrofit.adapter.mock.ResponseMock import retrofit2.http.GET interface ApiClientTest { @GET("test") - fun test(): CallK + fun test(): CallK @GET("testIO") - fun testIO(): IO + fun testIO(): IO } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt index 6c6409d0fa5..de18f23c2c4 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt @@ -1,12 +1,13 @@ package arrow.integrations.retrofit.adapter import arrow.effects.IO +import arrow.integrations.retrofit.adapter.retrofit.retrofit import arrow.test.UnitSpec import com.google.common.reflect.TypeToken import io.kotlintest.KTestJUnitRunner -import io.kotlintest.shouldBe -import io.kotlintest.shouldThrow -import io.kotlintest.specs.StringSpec +import io.kotlintest.matchers.shouldBe +import io.kotlintest.matchers.shouldThrow +import okhttp3.HttpUrl import org.junit.runner.RunWith import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -15,11 +16,7 @@ private val NO_ANNOTATIONS = emptyArray() @RunWith(KTestJUnitRunner::class) class Async2CallAdapterFactoryTest : UnitSpec() { - private val retrofit = Retrofit.Builder() - .baseUrl("http://localhost:1") - .addConverterFactory(GsonConverterFactory.create()) - .addCallAdapterFactory(Async2CallAdapterFactory.create()) - .build() + private val retrofit = retrofit(HttpUrl.parse("http://localhost:1")!!) private val factory = Async2CallAdapterFactory.create() diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt index 628771ea37c..40bb90487e3 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -5,6 +5,7 @@ import arrow.effects.ObservableK import arrow.effects.async import arrow.effects.fix import arrow.effects.monadDefer +import arrow.integrations.retrofit.adapter.mock.ResponseMock import arrow.integrations.retrofit.adapter.retrofit.retrofit import arrow.test.UnitSpec import io.kotlintest.KTestJUnitRunner @@ -17,9 +18,9 @@ import org.junit.runner.RunWith @RunWith(KTestJUnitRunner::class) class ProcCallBackTest : UnitSpec() { private val server = MockWebServer().apply { - enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) - enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) - enqueue(MockResponse().setBody("\"hello, world!\"").setResponseCode(200)) + enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) + enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) + enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) start() } @@ -28,34 +29,33 @@ class ProcCallBackTest : UnitSpec() { init { "should be able to parse answer with ForIO" { - val result = retrofit(baseUrl) - .create(ApiClientTest::class.java) + val result = createApiClientTest(baseUrl) .test() .async(IO.async()) .fix() .unsafeRunSync() - assertEquals(result, "hello, world!") + assertEquals(result, ResponseMock("hello, world!")) } "should be able to parse answer with ForObservableK" { - retrofit(baseUrl) - .create(ApiClientTest::class.java) + createApiClientTest(baseUrl) .test() .defer(ObservableK.monadDefer()) .fix() .observable .test() - .assertValue("hello, world!") + .assertValue(ResponseMock("hello, world!")) } "should be able to parse answer with IO" { - val result = retrofit(baseUrl) - .create(ApiClientTest::class.java) + val result = createApiClientTest(baseUrl) .testIO() .unsafeRunSync() - assertEquals(result, "hello, world!") + assertEquals(result, ResponseMock("hello, world!")) } } } + +private fun createApiClientTest(baseUrl: HttpUrl) = retrofit(baseUrl).create(ApiClientTest::class.java) \ No newline at end of file diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt new file mode 100644 index 00000000000..d5b09ef1799 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt @@ -0,0 +1,3 @@ +package arrow.integrations.retrofit.adapter.mock + +data class ResponseMock(val response: String) \ No newline at end of file diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt index c1a1aa672f8..4d5e8a4e62b 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt @@ -4,6 +4,7 @@ import arrow.integrations.retrofit.adapter.Async2CallAdapterFactory import okhttp3.HttpUrl import okhttp3.OkHttpClient import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory private fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder().build() @@ -11,6 +12,7 @@ private fun provideOkHttpClient(): OkHttpClient = private fun configRetrofit(retrofitBuilder: Retrofit.Builder) = retrofitBuilder .addCallAdapterFactory(Async2CallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) .client(provideOkHttpClient()) private fun getRetrofitBuilderDefaults(baseUrl: HttpUrl) = Retrofit.Builder().baseUrl(baseUrl) From 2b49077c68286d6e2d547bd45352058b662425b6 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Tue, 9 Oct 2018 22:47:40 -0300 Subject: [PATCH 03/10] simple pr corrections --- .../arrow-integrations-retrofit-adapter/build.gradle | 8 ++++---- .../retrofit/adapter/Async2CallAdapterFactoryTest.kt | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle index 0dc0dbc19f4..d8b3da128f0 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle +++ b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle @@ -1,16 +1,16 @@ -dependencies { - def retrofitVersion = "2.4.0" +def retrofitVersion = "2.4.0" +dependencies { compile project(':arrow-effects') compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" compile project(':arrow-annotations') - compile "com.squareup.retrofit2:retrofit:2.4.0" + compile "com.squareup.retrofit2:retrofit:$retrofitVersion" kapt project(':arrow-annotations-processor') kaptTest project(':arrow-annotations-processor') compileOnly project(':arrow-annotations-processor') testCompileOnly project(':arrow-annotations-processor') testCompile project(':arrow-test') - testCompile "com.squareup.retrofit2:converter-gson:${retrofitVersion}" + testCompile "com.squareup.retrofit2:converter-gson:$retrofitVersion" testCompile 'com.squareup.okhttp3:mockwebserver:3.11.0' testCompile project(':arrow-effects-rx2') } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt index de18f23c2c4..26d0db1df2c 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt @@ -14,12 +14,11 @@ import retrofit2.converter.gson.GsonConverterFactory private val NO_ANNOTATIONS = emptyArray() +private val retrofit = retrofit(HttpUrl.parse("http://localhost:1")!!) +private val factory = Async2CallAdapterFactory.create() + @RunWith(KTestJUnitRunner::class) class Async2CallAdapterFactoryTest : UnitSpec() { - private val retrofit = retrofit(HttpUrl.parse("http://localhost:1")!!) - - private val factory = Async2CallAdapterFactory.create() - init { "Non Async Class should return null" { factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit) shouldBe null From 06a778145711c7fd2dca22dca1c96ed80c654cf3 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Wed, 10 Oct 2018 10:00:15 -0300 Subject: [PATCH 04/10] small corrections in pr 2 --- .../retrofit/adapter}/Async2CallAdapterFactory.kt | 2 +- .../integrations/retrofit/adapter}/CallK.kt | 0 .../retrofit/adapter}/CallKind2CallAdapter.kt | 0 .../retrofit/adapter}/IO2CallAdapter.kt | 0 .../retrofit/adapter}/ResponseCallback.kt | 0 .../integrations/retrofit/adapter/ApiClientTest.kt | 14 +++++++++++++- .../retrofit/adapter/ProcCallBackTest.kt | 13 ++++++++----- 7 files changed, 22 insertions(+), 7 deletions(-) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/{arrow.integrations.retrofit.adapter => arrow/integrations/retrofit/adapter}/Async2CallAdapterFactory.kt (93%) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/{arrow.integrations.retrofit.adapter => arrow/integrations/retrofit/adapter}/CallK.kt (100%) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/{arrow.integrations.retrofit.adapter => arrow/integrations/retrofit/adapter}/CallKind2CallAdapter.kt (100%) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/{arrow.integrations.retrofit.adapter => arrow/integrations/retrofit/adapter}/IO2CallAdapter.kt (100%) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/{arrow.integrations.retrofit.adapter => arrow/integrations/retrofit/adapter}/ResponseCallback.kt (100%) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt similarity index 93% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt index 6ae3327f8e4..b86db7af1a1 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/Async2CallAdapterFactory.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt @@ -9,7 +9,7 @@ import java.lang.reflect.Type class Async2CallAdapterFactory : CallAdapter.Factory() { companion object { - fun create() = Async2CallAdapterFactory() + fun create(): Async2CallAdapterFactory = Async2CallAdapterFactory() } override fun get(returnType: Type, annotations: Array, retrofit: Retrofit): CallAdapter<*, *>? { diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt similarity index 100% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallK.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallKind2CallAdapter.kt similarity index 100% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/CallKind2CallAdapter.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallKind2CallAdapter.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt similarity index 100% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/IO2CallAdapter.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt similarity index 100% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow.integrations.retrofit.adapter/ResponseCallback.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt index 7e8e9bf3869..8b4a688de6f 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt @@ -2,13 +2,25 @@ package arrow.integrations.retrofit.adapter import arrow.effects.IO import arrow.integrations.retrofit.adapter.mock.ResponseMock +import retrofit2.Response import retrofit2.http.GET +import retrofit2.http.POST interface ApiClientTest { @GET("test") - fun test(): CallK + fun testCallK(): CallK + + @GET("testCallKResponse") + fun testCallKResponse(): CallK> @GET("testIO") fun testIO(): IO + + @GET("testIOResponse") + fun testIOResponse(): IO> + + @POST("testIOResponsePOST") + fun testIOResponsePost(): IO + } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt index 40bb90487e3..da077d1233e 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -18,8 +18,6 @@ import org.junit.runner.RunWith @RunWith(KTestJUnitRunner::class) class ProcCallBackTest : UnitSpec() { private val server = MockWebServer().apply { - enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) - enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) enqueue(MockResponse().setBody("{\"response\": \"hello, world!\"}").setResponseCode(200)) start() } @@ -27,10 +25,9 @@ class ProcCallBackTest : UnitSpec() { private val baseUrl: HttpUrl = server.url("/") init { - "should be able to parse answer with ForIO" { val result = createApiClientTest(baseUrl) - .test() + .testCallK() .async(IO.async()) .fix() .unsafeRunSync() @@ -40,7 +37,7 @@ class ProcCallBackTest : UnitSpec() { "should be able to parse answer with ForObservableK" { createApiClientTest(baseUrl) - .test() + .testCallK() .defer(ObservableK.monadDefer()) .fix() .observable @@ -55,6 +52,12 @@ class ProcCallBackTest : UnitSpec() { assertEquals(result, ResponseMock("hello, world!")) } + + "should be able to run a POST with UNIT as response" { + createApiClientTest(baseUrl) + .testIOResponsePost() + .unsafeRunSync() + } } } From ba265f8185750eda053d8d1c6b2e6ca2c766a6a2 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Wed, 10 Oct 2018 11:06:41 -0300 Subject: [PATCH 05/10] thinking about Response or just R --- .../integrations/retrofit/adapter/CallK.kt | 27 ++++++----- .../integrations/retrofit/adapter/Ext.kt | 18 ++++++++ .../retrofit/adapter/IO2CallAdapter.kt | 6 ++- .../retrofit/adapter/ResponseCallback.kt | 13 +----- .../retrofit/adapter/ApiClientTest.kt | 4 +- .../retrofit/adapter/ProcCallBackTest.kt | 46 +++++++++++++------ 6 files changed, 74 insertions(+), 40 deletions(-) create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt index 4d145643949..5239263799b 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt @@ -3,31 +3,34 @@ package arrow.integrations.retrofit.adapter import arrow.Kind import arrow.effects.typeclasses.Async import arrow.effects.typeclasses.MonadDefer +import arrow.typeclasses.ApplicativeError import arrow.typeclasses.MonadError import retrofit2.Call import retrofit2.HttpException import retrofit2.Response data class CallK(val call: Call) { - fun async(async: Async): Kind = - async.async { proc -> call.enqueue(ResponseCallback(proc)) } + fun async(async: Async): Kind> = + async.async { proc -> + call.enqueue(ResponseCallback(proc)) + } - fun defer(defer: MonadDefer): Kind = + fun defer(defer: MonadDefer): Kind> = defer { - handleResponse(call.execute()) + call.execute() } - fun catch(defer: MonadError): Kind = + fun catch(defer: MonadError): Kind> = defer.run { catch { - handleResponse(call.execute()) + call.execute() } } } -private fun handleResponse(response: Response) = - if (response.isSuccessful) { - response.body() ?: throw IllegalStateException("The request returned a null body") - } else { - throw HttpException(response) - } +//private fun handleResponse(response: Response) = +// if (response.isSuccessful) { +// response.body() ?: throw IllegalStateException("The request returned a null body") +// } else { +// throw HttpException(response) +// } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt new file mode 100644 index 00000000000..083c98c10a7 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt @@ -0,0 +1,18 @@ +package arrow.integrations.retrofit.adapter + +import arrow.Kind +import arrow.typeclasses.ApplicativeError +import retrofit2.HttpException +import retrofit2.Response + +fun Response.unwrapBody(apError: ApplicativeError): Kind = + if (this.isSuccessful) { + val body = this.body() + if (body != null) { + apError.just(body) + } else { + apError.raiseError(IllegalStateException("The request returned a null body")) + } + } else { + apError.raiseError(HttpException(this)) + } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt index 2aafa0e93f9..793a4b42b5e 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt @@ -3,10 +3,12 @@ package arrow.integrations.retrofit.adapter import arrow.effects.IO import retrofit2.Call import retrofit2.CallAdapter +import retrofit2.Response import java.lang.reflect.Type -class IO2CallAdapter(private val type: Type) : CallAdapter> { - override fun adapt(call: Call): IO = IO.async { proc -> call.enqueue(ResponseCallback(proc)) } +class IO2CallAdapter(private val type: Type) : CallAdapter>> { + override fun adapt(call: Call): IO> = + IO.async { proc -> call.enqueue(ResponseCallback(proc)) } override fun responseType(): Type = type } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt index e4912610272..d481cd8f648 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt @@ -8,18 +8,9 @@ import retrofit2.Callback import retrofit2.HttpException import retrofit2.Response -class ResponseCallback(private val proc: (Either) -> Unit) : Callback { +class ResponseCallback(private val proc: (Either>) -> Unit) : Callback { override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful) { - val body = response.body() - if (body != null) { - proc(body.right()) - } else { - proc(IllegalStateException("The request returned a null body").left()) - } - } else { - proc(HttpException(response).left()) - } + proc(response.right()) } override fun onFailure(call: Call, throwable: Throwable) { diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt index 8b4a688de6f..52083a90901 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt @@ -12,10 +12,10 @@ interface ApiClientTest { fun testCallK(): CallK @GET("testCallKResponse") - fun testCallKResponse(): CallK> + fun testCallKResponse(): CallK @GET("testIO") - fun testIO(): IO + fun testIO(): IO> @GET("testIOResponse") fun testIOResponse(): IO> diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt index da077d1233e..f259f7f1cc6 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -1,7 +1,11 @@ package arrow.integrations.retrofit.adapter +import arrow.core.Either +import arrow.core.applicativeError +import arrow.core.fix import arrow.effects.IO import arrow.effects.ObservableK +import arrow.effects.applicativeError import arrow.effects.async import arrow.effects.fix import arrow.effects.monadDefer @@ -9,6 +13,7 @@ import arrow.integrations.retrofit.adapter.mock.ResponseMock import arrow.integrations.retrofit.adapter.retrofit.retrofit import arrow.test.UnitSpec import io.kotlintest.KTestJUnitRunner +import io.kotlintest.matchers.fail import okhttp3.HttpUrl import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer @@ -26,31 +31,46 @@ class ProcCallBackTest : UnitSpec() { init { "should be able to parse answer with ForIO" { - val result = createApiClientTest(baseUrl) + createApiClientTest(baseUrl) .testCallK() .async(IO.async()) .fix() .unsafeRunSync() - - assertEquals(result, ResponseMock("hello, world!")) + .unwrapBody(Either.applicativeError()) + .fix() + .fold({ throwable -> + fail("The requested terminated with an exception. Message: ${throwable.message}") + }, { responseMock -> + assertEquals(ResponseMock("hello, world!"), responseMock) + }) } "should be able to parse answer with ForObservableK" { - createApiClientTest(baseUrl) - .testCallK() - .defer(ObservableK.monadDefer()) - .fix() - .observable - .test() - .assertValue(ResponseMock("hello, world!")) + with(ObservableK) { + createApiClientTest(baseUrl) + .testCallK() + .defer(monadDefer()) + .fix() + .flatMap { response -> + response.unwrapBody(applicativeError()).fix() + } + .observable + .test() + .assertValue(ResponseMock("hello, world!")) + } } "should be able to parse answer with IO" { - val result = createApiClientTest(baseUrl) + createApiClientTest(baseUrl) .testIO() .unsafeRunSync() - - assertEquals(result, ResponseMock("hello, world!")) + .unwrapBody(Either.applicativeError()) + .fix() + .fold({ throwable -> + fail("The requested terminated with an exception. Message: ${throwable.message}") + }, { responseMock -> + assertEquals(ResponseMock("hello, world!"), responseMock) + }) } "should be able to run a POST with UNIT as response" { From 524035446eb16b0dc4498c6dd6ae3e0cbf83cd2a Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Wed, 10 Oct 2018 23:23:27 -0300 Subject: [PATCH 06/10] removing IO adapter and pr adjustments --- infographic/arrow-infographic.txt | 2 +- .../adapter/Async2CallAdapterFactory.kt | 10 ++--- .../integrations/retrofit/adapter/CallK.kt | 9 ---- .../retrofit/adapter/IO2CallAdapter.kt | 14 ------- .../retrofit/adapter/ResponseCallback.kt | 1 - .../adapter/Async2CallAdapterFactoryTest.kt | 10 ++--- .../retrofit/adapter/ProcCallBackTest.kt | 18 ++------ .../retrofit/adapter/ResponseCallbackTest.kt | 41 +++++++++++++++++++ .../retrofit/adapter/mock/ResponseMock.kt | 2 +- .../adapter/{ => retrofit}/ApiClientTest.kt | 13 ++---- .../retrofit/adapter/retrofit/Retrofit.kt | 2 +- 11 files changed, 58 insertions(+), 64 deletions(-) delete mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt rename modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/{ => retrofit}/ApiClientTest.kt (53%) diff --git a/infographic/arrow-infographic.txt b/infographic/arrow-infographic.txt index 8658b400a4f..a8f1f93a932 100644 --- a/infographic/arrow-infographic.txt +++ b/infographic/arrow-infographic.txt @@ -41,7 +41,7 @@ [Functor]<-[Comonad] [Functor]<-[FunctorFilter] [Functor]<-[Traverse] -[Index]<-[Index Instances|ListKIndexInstance|MapKIndexInstance|NonEmptyListIndexInstance|SequenceKIndexInstance|ListKFilterIndexInstance|MapKFilterIndexInstance|NonEmptyListFilterIndexInstance|SequenceKFilterIndexInstance] +[Index]<-[Index Instances|ListKIndexInstance|MapKIndexInstance|NonEmptyListIndexInstance|SequenceKIndexInstance] [Invariant]<-[Invariant Instances|ConstInvariant|MonoidInvariantInstance] [Invariant]<-[Contravariant] [Invariant]<-[Functor] diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt index b86db7af1a1..42a32187f86 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt @@ -1,6 +1,5 @@ package arrow.integrations.retrofit.adapter -import arrow.effects.IO import retrofit2.CallAdapter import retrofit2.Retrofit import java.lang.reflect.ParameterizedType @@ -23,10 +22,10 @@ class Async2CallAdapterFactory : CallAdapter.Factory() { val effectType = CallAdapter.Factory.getParameterUpperBound(0, returnType) - return when (rawType) { - IO::class.java -> IO2CallAdapter(effectType) - CallK::class.java -> CallKind2CallAdapter(effectType) - else -> null + return if (rawType == CallK::class.java) { + CallKind2CallAdapter(effectType) + } else { + null } } } @@ -35,4 +34,3 @@ private fun parseTypeName(type: Type) = type.typeName .split(".") .last() - diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt index 5239263799b..8133f625534 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt @@ -3,10 +3,8 @@ package arrow.integrations.retrofit.adapter import arrow.Kind import arrow.effects.typeclasses.Async import arrow.effects.typeclasses.MonadDefer -import arrow.typeclasses.ApplicativeError import arrow.typeclasses.MonadError import retrofit2.Call -import retrofit2.HttpException import retrofit2.Response data class CallK(val call: Call) { @@ -27,10 +25,3 @@ data class CallK(val call: Call) { } } } - -//private fun handleResponse(response: Response) = -// if (response.isSuccessful) { -// response.body() ?: throw IllegalStateException("The request returned a null body") -// } else { -// throw HttpException(response) -// } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt deleted file mode 100644 index 793a4b42b5e..00000000000 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/IO2CallAdapter.kt +++ /dev/null @@ -1,14 +0,0 @@ -package arrow.integrations.retrofit.adapter - -import arrow.effects.IO -import retrofit2.Call -import retrofit2.CallAdapter -import retrofit2.Response -import java.lang.reflect.Type - -class IO2CallAdapter(private val type: Type) : CallAdapter>> { - override fun adapt(call: Call): IO> = - IO.async { proc -> call.enqueue(ResponseCallback(proc)) } - - override fun responseType(): Type = type -} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt index d481cd8f648..c4a4ccf4672 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/ResponseCallback.kt @@ -5,7 +5,6 @@ import arrow.core.left import arrow.core.right import retrofit2.Call import retrofit2.Callback -import retrofit2.HttpException import retrofit2.Response class ResponseCallback(private val proc: (Either>) -> Unit) : Callback { diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt index 26d0db1df2c..3fb80bd5fc1 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactoryTest.kt @@ -9,8 +9,6 @@ import io.kotlintest.matchers.shouldBe import io.kotlintest.matchers.shouldThrow import okhttp3.HttpUrl import org.junit.runner.RunWith -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory private val NO_ANNOTATIONS = emptyArray() @@ -20,7 +18,7 @@ private val factory = Async2CallAdapterFactory.create() @RunWith(KTestJUnitRunner::class) class Async2CallAdapterFactoryTest : UnitSpec() { init { - "Non Async Class should return null" { + "Non CallK Class should return null" { factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit) shouldBe null } @@ -36,11 +34,9 @@ class Async2CallAdapterFactoryTest : UnitSpec() { exceptionIO.message shouldBe "Return type must be parameterized as IO or IO" } - "Should work for all types" { - factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit)!! - .responseType() shouldBe String::class.java + "Should work for CallK types" { factory.get(object : TypeToken>() {}.type, NO_ANNOTATIONS, retrofit)!! .responseType() shouldBe String::class.java } } -} \ No newline at end of file +} diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt index f259f7f1cc6..e8b4b659c93 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -10,6 +10,7 @@ import arrow.effects.async import arrow.effects.fix import arrow.effects.monadDefer import arrow.integrations.retrofit.adapter.mock.ResponseMock +import arrow.integrations.retrofit.adapter.retrofit.ApiClientTest import arrow.integrations.retrofit.adapter.retrofit.retrofit import arrow.test.UnitSpec import io.kotlintest.KTestJUnitRunner @@ -60,25 +61,14 @@ class ProcCallBackTest : UnitSpec() { } } - "should be able to parse answer with IO" { - createApiClientTest(baseUrl) - .testIO() - .unsafeRunSync() - .unwrapBody(Either.applicativeError()) - .fix() - .fold({ throwable -> - fail("The requested terminated with an exception. Message: ${throwable.message}") - }, { responseMock -> - assertEquals(ResponseMock("hello, world!"), responseMock) - }) - } - "should be able to run a POST with UNIT as response" { createApiClientTest(baseUrl) .testIOResponsePost() + .async(IO.async()) + .fix() .unsafeRunSync() } } } -private fun createApiClientTest(baseUrl: HttpUrl) = retrofit(baseUrl).create(ApiClientTest::class.java) \ No newline at end of file +private fun createApiClientTest(baseUrl: HttpUrl) = retrofit(baseUrl).create(ApiClientTest::class.java) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt new file mode 100644 index 00000000000..7b12d82ea88 --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt @@ -0,0 +1,41 @@ +package arrow.integrations.retrofit.adapter + +import arrow.effects.IO +import arrow.effects.async +import arrow.effects.fix +import arrow.integrations.retrofit.adapter.retrofit.ApiClientTest +import arrow.integrations.retrofit.adapter.retrofit.retrofit +import arrow.test.UnitSpec +import io.kotlintest.KTestJUnitRunner +import io.kotlintest.matchers.fail +import okhttp3.HttpUrl +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.runner.RunWith + +@RunWith(KTestJUnitRunner::class) +class ResponseCallbackTest : UnitSpec() { + private val server = MockWebServer().apply { + enqueue(MockResponse().setBody("{response: \"hello, world!\"}").setResponseCode(200)) + start() + } + + private val baseUrl: HttpUrl = server.url("/") + + init { + "bad deserialization should return Either.Left" { + createApiClientTest(baseUrl) + .testCallK() + .async(IO.async()) + .fix() + .attempt() + .unsafeRunSync() + .fold({ + }, { + fail("The request should have not terminated correctly") + }) + } + } +} + +private fun createApiClientTest(baseUrl: HttpUrl) = retrofit(baseUrl).create(ApiClientTest::class.java) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt index d5b09ef1799..9bef63d208b 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/mock/ResponseMock.kt @@ -1,3 +1,3 @@ package arrow.integrations.retrofit.adapter.mock -data class ResponseMock(val response: String) \ No newline at end of file +data class ResponseMock(val response: String) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/ApiClientTest.kt similarity index 53% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/ApiClientTest.kt index 52083a90901..2897e792f11 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ApiClientTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/ApiClientTest.kt @@ -1,8 +1,7 @@ -package arrow.integrations.retrofit.adapter +package arrow.integrations.retrofit.adapter.retrofit -import arrow.effects.IO +import arrow.integrations.retrofit.adapter.CallK import arrow.integrations.retrofit.adapter.mock.ResponseMock -import retrofit2.Response import retrofit2.http.GET import retrofit2.http.POST @@ -14,13 +13,7 @@ interface ApiClientTest { @GET("testCallKResponse") fun testCallKResponse(): CallK - @GET("testIO") - fun testIO(): IO> - - @GET("testIOResponse") - fun testIOResponse(): IO> - @POST("testIOResponsePOST") - fun testIOResponsePost(): IO + fun testIOResponsePost(): CallK } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt index 4d5e8a4e62b..e079cfc80a6 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/retrofit/Retrofit.kt @@ -17,4 +17,4 @@ private fun configRetrofit(retrofitBuilder: Retrofit.Builder) = private fun getRetrofitBuilderDefaults(baseUrl: HttpUrl) = Retrofit.Builder().baseUrl(baseUrl) -fun retrofit(baseUrl: HttpUrl): Retrofit = configRetrofit(getRetrofitBuilderDefaults(baseUrl)).build() \ No newline at end of file +fun retrofit(baseUrl: HttpUrl): Retrofit = configRetrofit(getRetrofitBuilderDefaults(baseUrl)).build() From 1a7c2cd13fe05413523cbae719ce913c0b987b04 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Thu, 18 Oct 2018 20:40:08 -0300 Subject: [PATCH 07/10] refactor to extension functions --- .../integrations/retrofit/adapter/CallK.kt | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt index 8133f625534..0ae81342189 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt @@ -8,20 +8,23 @@ import retrofit2.Call import retrofit2.Response data class CallK(val call: Call) { - fun async(async: Async): Kind> = - async.async { proc -> - call.enqueue(ResponseCallback(proc)) - } + fun async(AC: Async): Kind> = call.runInAsyncContext(AC) - fun defer(defer: MonadDefer): Kind> = - defer { - call.execute() - } + fun defer(defer: MonadDefer): Kind> = call.runSyncDeferred(defer) - fun catch(defer: MonadError): Kind> = - defer.run { - catch { - call.execute() - } - } + fun catch(monadError: MonadError): Kind> = call.runSyncCatch(monadError) } + +fun Call.runInAsyncContext(AC: Async): Kind> = + AC.async { callback -> + enqueue(ResponseCallback(callback)) + } + +fun Call.runSyncDeferred(defer: MonadDefer): Kind> = defer { execute() } + +fun Call.runSyncCatch(monadError: MonadError): Kind> = + monadError.run { + catch { + execute() + } + } From 7dd20ef2271954a8db8effcee6479a07dcf0ce3e Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Thu, 18 Oct 2018 23:27:38 -0300 Subject: [PATCH 08/10] pr fix --- .../integrations/retrofit/adapter/CallK.kt | 14 -------- .../integrations/retrofit/adapter/Ext.kt | 18 ---------- .../integrations/retrofit/adapter/syntax.kt | 36 +++++++++++++++++++ 3 files changed, 36 insertions(+), 32 deletions(-) delete mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt create mode 100644 modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt index 0ae81342189..6c0b378f0d6 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt @@ -14,17 +14,3 @@ data class CallK(val call: Call) { fun catch(monadError: MonadError): Kind> = call.runSyncCatch(monadError) } - -fun Call.runInAsyncContext(AC: Async): Kind> = - AC.async { callback -> - enqueue(ResponseCallback(callback)) - } - -fun Call.runSyncDeferred(defer: MonadDefer): Kind> = defer { execute() } - -fun Call.runSyncCatch(monadError: MonadError): Kind> = - monadError.run { - catch { - execute() - } - } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt deleted file mode 100644 index 083c98c10a7..00000000000 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Ext.kt +++ /dev/null @@ -1,18 +0,0 @@ -package arrow.integrations.retrofit.adapter - -import arrow.Kind -import arrow.typeclasses.ApplicativeError -import retrofit2.HttpException -import retrofit2.Response - -fun Response.unwrapBody(apError: ApplicativeError): Kind = - if (this.isSuccessful) { - val body = this.body() - if (body != null) { - apError.just(body) - } else { - apError.raiseError(IllegalStateException("The request returned a null body")) - } - } else { - apError.raiseError(HttpException(this)) - } diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt new file mode 100644 index 00000000000..1d917dfad1d --- /dev/null +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt @@ -0,0 +1,36 @@ +package arrow.integrations.retrofit.adapter + +import arrow.Kind +import arrow.effects.typeclasses.Async +import arrow.effects.typeclasses.MonadDefer +import arrow.typeclasses.ApplicativeError +import arrow.typeclasses.MonadError +import retrofit2.Call +import retrofit2.HttpException +import retrofit2.Response + +fun Response.unwrapBody(apError: ApplicativeError): Kind = + if (this.isSuccessful) { + val body = this.body() + if (body != null) { + apError.just(body) + } else { + apError.raiseError(IllegalStateException("The request returned a null body")) + } + } else { + apError.raiseError(HttpException(this)) + } + +fun Call.runInAsyncContext(AC: Async): Kind> = + AC.async { callback -> + enqueue(ResponseCallback(callback)) + } + +fun Call.runSyncDeferred(defer: MonadDefer): Kind> = defer { execute() } + +fun Call.runSyncCatch(monadError: MonadError): Kind> = + monadError.run { + catch { + execute() + } + } From a6b73e864a024d487a1fc837115b57b0942b9d5a Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Mon, 22 Oct 2018 11:35:38 -0300 Subject: [PATCH 09/10] fixing modules and imports --- .../arrow-integrations-retrofit-adapter/build.gradle | 3 +++ .../integrations/retrofit/adapter/ProcCallBackTest.kt | 8 ++++---- .../integrations/retrofit/adapter/ResponseCallbackTest.kt | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle index d8b3da128f0..84d3a4f25aa 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle +++ b/modules/integrations/arrow-integrations-retrofit-adapter/build.gradle @@ -2,6 +2,7 @@ def retrofitVersion = "2.4.0" dependencies { compile project(':arrow-effects') + compile project(':arrow-typeclasses') compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" compile project(':arrow-annotations') compile "com.squareup.retrofit2:retrofit:$retrofitVersion" @@ -13,6 +14,8 @@ dependencies { testCompile "com.squareup.retrofit2:converter-gson:$retrofitVersion" testCompile 'com.squareup.okhttp3:mockwebserver:3.11.0' testCompile project(':arrow-effects-rx2') + testCompile project(':arrow-effects-rx2-instances') + testCompile project(':arrow-effects-instances') } apply from: rootProject.file('gradle/gradle-mvn-push.gradle') diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt index e8b4b659c93..9f1faa058f9 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ProcCallBackTest.kt @@ -1,14 +1,14 @@ package arrow.integrations.retrofit.adapter import arrow.core.Either -import arrow.core.applicativeError import arrow.core.fix import arrow.effects.IO import arrow.effects.ObservableK -import arrow.effects.applicativeError -import arrow.effects.async import arrow.effects.fix -import arrow.effects.monadDefer +import arrow.effects.instances.io.async.async +import arrow.effects.observablek.applicativeError.applicativeError +import arrow.effects.observablek.monadDefer.monadDefer +import arrow.instances.either.applicativeError.applicativeError import arrow.integrations.retrofit.adapter.mock.ResponseMock import arrow.integrations.retrofit.adapter.retrofit.ApiClientTest import arrow.integrations.retrofit.adapter.retrofit.retrofit diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt index 7b12d82ea88..24c4a4b8e89 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/test/kotlin/arrow/integrations/retrofit/adapter/ResponseCallbackTest.kt @@ -1,8 +1,8 @@ package arrow.integrations.retrofit.adapter import arrow.effects.IO -import arrow.effects.async import arrow.effects.fix +import arrow.effects.instances.io.async.async import arrow.integrations.retrofit.adapter.retrofit.ApiClientTest import arrow.integrations.retrofit.adapter.retrofit.retrofit import arrow.test.UnitSpec From 9cc9539649f4edbc96390d5ba240bb275d9d92e2 Mon Sep 17 00:00:00 2001 From: Leandro Borges Ferreira Date: Mon, 22 Oct 2018 20:30:41 -0300 Subject: [PATCH 10/10] pr fixes --- .../main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt | 2 +- .../{Async2CallAdapterFactory.kt => CallKindAdapterFactory.kt} | 0 .../main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/{Async2CallAdapterFactory.kt => CallKindAdapterFactory.kt} (100%) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt index 6c0b378f0d6..2a62f29bf20 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallK.kt @@ -8,7 +8,7 @@ import retrofit2.Call import retrofit2.Response data class CallK(val call: Call) { - fun async(AC: Async): Kind> = call.runInAsyncContext(AC) + fun async(AC: Async): Kind> = call.runAsync(AC) fun defer(defer: MonadDefer): Kind> = call.runSyncDeferred(defer) diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallKindAdapterFactory.kt similarity index 100% rename from modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/Async2CallAdapterFactory.kt rename to modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/CallKindAdapterFactory.kt diff --git a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt index 1d917dfad1d..9d9e94aa57b 100644 --- a/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt +++ b/modules/integrations/arrow-integrations-retrofit-adapter/src/main/kotlin/arrow/integrations/retrofit/adapter/syntax.kt @@ -21,7 +21,7 @@ fun Response.unwrapBody(apError: ApplicativeError): Kind apError.raiseError(HttpException(this)) } -fun Call.runInAsyncContext(AC: Async): Kind> = +fun Call.runAsync(AC: Async): Kind> = AC.async { callback -> enqueue(ResponseCallback(callback)) }