https://kotlinlang.org logo
Title
o

oshai

11/05/2018, 3:26 PM
I want to create an integration module for our async lib, right now it is using
CompleteableFuture
. So I thought about converting it to either
suspend fun
by using the
await
extension. Another option is to create methods that return
Deferred
. What do you think is a better approach?
Here is an example how it is done now:
z

Zach Klippenstein (he/him) [MOD]

11/05/2018, 5:38 PM
o

oshai

11/05/2018, 6:35 PM
Its not exactly the same case because I have a CompletableFuture so turning it into deferred do not involve calling async
d

dave08

11/05/2018, 8:57 PM
I think the better way is to use
suspendCancellableCoroutine { }
I think that's what await does... since Deferred and async is more for parallel decomposition, not for just suspending on an async api.
g

gildor

11/06/2018, 12:02 AM
+1 to Dave for native support using suspendCancellableCoroutine and suspend functions instead of wrapping to Deferred
o

oshai

11/06/2018, 6:13 AM
There is a jdk 8 assistance lib in my case so it is even easier
feedback is welcome
g

gildor

11/06/2018, 10:51 AM
Using existing CompletableFeature API + coroutines adaptet is easiest solution and do not require change of existing code, so completely fine imo
d

dave08

11/06/2018, 11:33 AM
It might be nice to have a separate class for coroutines, since having
await...
in all the names suggests async operations as in the guide, and one using the coroutines version will probably not be using the regular one. Maybe a
Connection
class under a
coroutines
namespace or something?
o

oshai

11/06/2018, 11:39 AM
@dave08 - the problem is that those are extension methods on
Connection
. they are in a seperate class but still I want to diffrentiate them somehow from the name of methods in the original interface
d

dave08

11/06/2018, 11:49 AM
I mean a seperate
interface
that is implemented for coroutine use, then a regular connection could be "transformed" to that interface. Something like:
fun Connection.coroutinesWrapper(): CoroutineConnection = CoroutineConnectionWrapper(this)
. Vert.x does what you're currently doing for its Rx support... along with new generated classes... I think it wasn't so intuitive.
o

oshai

11/06/2018, 12:38 PM
@dave08 that looks like a nice idea, let me try to implement that
d

dave08

11/06/2018, 4:39 PM
Looks good! But I think there should be a seperate
interface
for it for mocking/testing purposes and also in
suspend fun <A> inTransaction(f: (Connection) -> CompletableFuture<A>): A = connection.inTransaction(f).await()
it seems funny that there's a
CompletableFuture
there... I think they shouldn't be mixed in here... @oshai
I think it should be something like
suspend fun <A> inTransaction(f: suspend (Connection) -> A): A
o

oshai

11/06/2018, 4:42 PM
good input thanks! will add that. since I need the connection I don't have an idea to do it with an interface only, I will post again with changes
d

dave08

11/06/2018, 4:50 PM
Why would you have the implementation inside the interface? You could have
class SuspendableConnection(val connection: Connection) { ... }
with the actual implementation, and not have
val connection
inside the interface at all... unless you think someone would need the original Connection instance? @oshai And what about the
inTransaction
with the
CompletableFuture
?
Otherwise one would have to mock that Connection instance too...
o

oshai

11/06/2018, 4:58 PM
@dave08 - this way I don't have to duplicate all methods between interface and implementation, I will take a look on the inTrasaction soon
d

dave08

11/06/2018, 5:00 PM
It looks like the TransactionHelper can be redone without the Executor using coroutines... You don't have to implement the methods in the interface at all, just declare them, and override them in the implementation IDEA can generate the stubs for you... that way, you'll make it MUCH easier for testing/mocking purposes...
o

oshai

11/06/2018, 5:06 PM
ok, is there a chance you would like to PR because I don't think I fully understand what you mean?
@dave08 ^^
gist is also ok
d

dave08

11/06/2018, 5:20 PM
I'll try to pull out some time 🙂
I'm not sure how
inTransaction
is used, so I can't give you advice on it too much.. who passes that
CompletableFuture
to the lambda
f
it receives...?
The last query made in the transaction which gives it the
A
?
now I guess
inTransaction
is much more clear
d

dave08

11/06/2018, 5:49 PM
I guess it's a bit late to rewrite everything, but I think I would have wrote the core in coroutines, and exposed an interface for Java with
Deferred.asCompletableFuture
🙃, the code would have been MUCH simpler...
You could still migrate piece by piece, until you get there, using these utility functions as glue... 😉
o

oshai

11/06/2018, 5:52 PM
Well, since I migrated from scala futures moving to completable future was much easier
d

dave08

11/06/2018, 5:54 PM
Yeah, coroutines isn't easy at first... it's great you got this far like this! I'm just wondering if
inTransaction
is not dependant on Mysql or Postgres specifics... it seems like you implemented them in each one individually..?
o

oshai

11/06/2018, 6:49 PM
I will explain in DM as it is off topic for this thread