-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add async API (2) #1258
Add async API (2) #1258
Conversation
298d992
to
1c15c4a
Compare
1c15c4a
to
36a30f1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments on the second commit
driver-core/src/main/com/mongodb/internal/async/SingleResultCallback.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve one thread and commented back on another.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve one thread and commented back on another.
import java.util.function.Supplier; | ||
|
||
/** | ||
* See tests for usage (AsyncFunctionsTest). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer that usage documentation is placed in the code rather than the test. It will be easier for maintainers to refer to it if it's here. And that's where all of our existing internal Javadoc is, so it will be less surprising.
Of all the new interfaces, this seems like the best place to put it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved; I find that I often look at the test code (more often than the docs) to confirm that I am using the API correctly.
if (result != null) { | ||
complete(result); | ||
} else { | ||
complete((SingleResultCallback<Void>) SingleResultCallback.this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing the whole block with
onResult(result, null)
seems preferable to this cast.
Firstly, I really like where this API is going. I initially got confused as the language wasn't as I was expected coming from a functional background (eg. Scala and RxJava / Reactor). This got me thinking, and the API could be simplified by adopting some methods akin to those in Project Reactors Mono eg I did a quick POC based off this work and it provides the following methods:
The mapping between this API would be:
You can compare the tests here: AsyncFunctionsTest and MonoTest Basically, its very similar but follows a more conventional reactive API rather that trying to coherse sync Functional types (Runnable, Supplier, Consumer) into an async paradigm. Let me know what you think? |
@rozza Interesting! Thanks for digging into the options, this is the sort of thing that will help us round out the API. The most important thing, in my view, is the function composition that happens in "then" methods, which allows us to flatten nested async calls, and monadically short-circuit ensuing calls (which is comparable to exception handling). Both API surfaces build on this, so ultimately the APIs are much closer to each other than, for example, our current approach, or using reactive. Of course there are specific differences that arise, which can be individually addressed:
While Option 2 can be shorter (though typically by only 1 line) in simple cases, in typical non-simple cases, where clarity is all the more important, it takes up more lines, and has substantial indentation. It is also less consistent, since it partly uses the "Option 1" approach when there is plain code mixed in (see then, vs onErrorResume above), which often happens. The biggest down-side is that it mixes boilerplate with normal code, which must be compared against a sync counterpart, whereas Option 1 puts all boilerplate on its own lines. I find matching the first option up with its async counterpart trivial (I just skim vertically along the suitable indentation level), but the second much more difficult.
|
driver-core/src/test/functional/com/mongodb/client/TestListener.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/SingleResultCallback.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/AsyncSupplier.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/AsyncSupplier.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/AsyncRunnable.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/AsyncRunnable.java
Outdated
Show resolved
Hide resolved
driver-core/src/main/com/mongodb/internal/async/AsyncRunnable.java
Outdated
Show resolved
Hide resolved
@katcharov, thanks for the feedback. My aim was not to create new language (and be barrier for learning / adoption) but rather to used established names in functional / composable code. I picked the name The Taking the example code - there are no runnables, just a flow of methods / and a catch:
Even with Similar to |
driver-core/src/main/com/mongodb/internal/async/SingleResultCallback.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Valentin Kovalenko <[email protected]>
I like the general approach and had some naming concerns that are pretty trivial. I will add a ticket for future consideration regarding adapting this approach, and extending it to provide a chainable (Monadic) API. That does not block this work, and as there are 2 LGTMs I've removed myself from the review. |
JAVA-5082
This is #1234, but with demo refactoring removed (that is, this is just the async API, with no other changes).
The first commit, "Add async functions", was reviewed as part of #1134 , but can be further reviewed. Other commits are all new non-reviewed code.