I want to create an integration module for our asy...
# coroutines
o
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
o
Its not exactly the same case because I have a CompletableFuture so turning it into deferred do not involve calling async
d
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
+1 to Dave for native support using suspendCancellableCoroutine and suspend functions instead of wrapping to Deferred
o
There is a jdk 8 assistance lib in my case so it is even easier
feedback is welcome
g
Using existing CompletableFeature API + coroutines adaptet is easiest solution and do not require change of existing code, so completely fine imo
d
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
@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
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
@dave08 that looks like a nice idea, let me try to implement that
d
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
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
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
@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
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
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
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
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
Well, since I migrated from scala futures moving to completable future was much easier
d
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
I will explain in DM as it is off topic for this thread