Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrofit+Arrow to Ktor Client+Arrow migration #3354

Open
postfixNotation opened this issue Jan 22, 2024 · 8 comments
Open

Retrofit+Arrow to Ktor Client+Arrow migration #3354

postfixNotation opened this issue Jan 22, 2024 · 8 comments

Comments

@postfixNotation
Copy link

As of today I'm using Retroft in combination with Moshi for Serialization and Arrow's Either API for return type specifications, for instance suspended network calls return something like Either<CallError, Dto> where CallError is an Arrow API.

I'm slowly migrating my app to be multiplatform capable, so I'm replacing APIs like java.time.* with kotlinx.datetime.* and so on. My problem is, there's a Retrofit integration with Arrow but not an equivalent for Ktor as far as I know.

So my question is: what would be the best pattern or strategy to replace Retrofit with Ktor client so that my client code doesn't break? This is kind of tricky since CallError is located in arrow.retrofit.adapter.either.networkhandling, so it's part of Retrofit's integration API...
For clarification: I'm also migrating from Moshi to kotlinx.serialization, maybe this helps somehow.

@nomisRev
Copy link
Member

Hey @postfixNotation,

I think there are a couple of things we can do, but not sure which is the best one 🤔 It also depends a bit on your use-case.

  1. There is also Ktorfit, but the adapter we have doesn't work with that one but it should be very easy to port.

  2. We write a new module for Ktor, which I think multiple people have shown interest in. However, there are two options here

  • Re-use CallError from Retrofit library, this would be least breaking for you
  • Use different sealed class for Ktor, since it support different kind of errors. I think for Ktor Either<HttpStatusCode, A> might be better. Or data class CallError(val code: HttpStatusCode, val call: ApplicationCall), and Either<CallError, A>.

@postfixNotation
Copy link
Author

Hi @nomisRev,

thanks for your quick and helpful reply!

Ktorfit looks pretty neat and it's good to know about this option. However I'm planning to delve into Ktor extensively since I'd also like to write my own backend. Also I want my project to have as few dependencies as possible and also to mostly rely on robust long-term solutions. Depending on intermediary layers/services is probably not sustainable for my requirements.

A module, as proposed in your last message, would be amazing and also very beneficial for the whole community. "Retrofit's" CallError might be exposed as a typealias in an appropriately scoped package of such a module which would be least breaking for me, as of my understanding. But a correctly modeled approach, as described in your last point, might probably be the most beneficial solution.

Is there an estimation of how long this might take?
Thanks!

@nomisRev
Copy link
Member

Hey @postfixNotation,

Is there an estimation of how long this might take?

There is only a couple of maintainers, and sadly this is on none of our priority list. We already have more work than we can handle in our spare free time.

However, if you'd like to work on this I'd be more than happy to guide, and support you! ☺️

@postfixNotation
Copy link
Author

Hi @nomisRev,

As soon as I migrate from Retrofit to Ktor to make my app multiplatform compatible I will consider working on this feature. Right now I have zero knowledge of and experience with Ktor's API surface and paradigm which is why it's hard to make any commitments.

But this could be my first open source contribution which is pretty exciting and a good learning experience, so we'll see :-)

I'm also looking for a good multiplatform DI solution but the existing one's are too risky since many of them don't provide compile time safety. I came across Kotlin context receivers and their potential ability to act as 3rd party DI framework replacement.

I know it's not related to this issue but is there still any work in progress from Arrow's site with respect to this functionality? The respective repository seems not to be actively maintained anymore.

Have a great weekend!

@abendt
Copy link
Contributor

abendt commented May 3, 2024

Hi @nomisRev and @postfixNotation

would be interested to work on that and provide a PR

I have experimented a bit and already have a basic adapter for KtorFit but would also like to check out option #2

Please let me know if that's OK for both of you

@postfixNotation
Copy link
Author

Hi @nomisRev and @postfixNotation

would be interested to work on that and provide a PR

I have experimented a bit and already have a basic adapter for KtorFit but would also like to check out option #2

Please let me know if that's OK for both of you

It would be amazing if someone worked on this issue since I have different priorities at the moment :-)

@abendt
Copy link
Contributor

abendt commented May 3, 2024

Here is my result so far: https://github.com/abendt/arrow-ktor/blob/main/src/main/kotlin/demo/ExampleApi.kt

There you can see how you can use Either<Exception, A> in your Ktorfit client. Should also be possible to support some custom CallError on the left side.

Let me know if that looks useful to you and what other requirements & ideas you might have

@postfixNotation
Copy link
Author

Here is my result so far: https://github.com/abendt/arrow-ktor/blob/main/src/main/kotlin/demo/ExampleApi.kt

There you can see how you can use Either<Exception, A> in your Ktorfit client. Should also be possible to support some custom CallError on the left side.

Let me know if that looks useful to you and what other requirements & ideas you might have

Hi @abendt!
This looks pretty interesting and very easy to use.

I'm still stuck with Retrofit but I assume I would migrate to Ktor Client without using Ktorfit. Although it looks pretty straight forward to use.

I think the most pragmatic and helpful approach would be to work on solution 2.2) of @nomisRev post above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants