Raul,

Yes, my design is an attempt to address exactly the problems you've
mentioned (get rid of state, better type safety, cleaner code).
I'm not an expert in reactive streams, but I believe Future is the most low
level feature possible here, so higher level abstractions
can be build using it.

Sergi


2015-10-13 19:32 GMT+03:00 Dmitriy Setrakyan <[email protected]>:

> On Tue, Oct 13, 2015 at 9:19 AM, Raul Kripalani <[email protected]> wrote:
>
> > I like this approach.
> >
> > To me, the current API is messy and hacky, and even "spiritually"
> > contradictory, may I say. The whole raison d'être of the current approach
> > seems to be to achieve parity of APIs of IgniteCompute, IgniteMessaging,
> > etc. in sync and async modes. However, truth of the matter is that we
> only
> > end up honouring half of the API in async mode: the method entry point
> and
> > parameters. The method return type is basically ignored, because all
> > methods in async mode return null since the "virtual" return type is now
> a
> > Future that the user must obtain with a separate code. To me, this is a
> > code smell.
> >
> > Moreover, I would argue that keeping a state (even if in a ThreadLocal)
> > also makes certain use cases impossible or buggy, like Nikita
> illustrated,
> > e.g. passing IgniteCache, IgniteCompute, etc down the stack.
> >
> > In fact, keeping a state in async mode and not in sync is problematic
> > because – to the eyes of the user – they're always interacting with the
> > neutral interfaces IgniteCompute, IgniteCache, etc. They have no
> indication
> > of when a state is being kept and when not – only through documentation,
> > common sense and human memory – something that's error-prone.
> >
> > Obviously the verbosity and fluency of user's code is also a factor to
> > consider, but to me it is secondary. The above points are enough to
> > advocate changing the async APIs.
> >
> > Finally, looking to the future, the current approach does make Ignite
> > difficult to integrate with Reactive Streams. So it's great we're
> > discussing it.
> >
> > @Sergey, the approach you propose would entail adding Async interface
> > variants for each functionality. This is a step in the opposite direction
> > of the spirit of the current API, am I correct? Since this is a change in
> > direction, I would like for most of the team to approve or disapprove.
> >
>
> I personally like Sergey's design. I actually don't see it as a step in the
> opposite direction. I think it achieves the same goal, but in a much
> cleaner fashion. Moreover, it seems to be .NET-friendly as well.
>
>
> >
> > Regards,
> >
> > *Raúl Kripalani*
> > PMC & Committer @ Apache Ignite, Apache Camel | Integration, Big Data and
> > Messaging Engineer
> > http://about.me/raulkripalani | http://www.linkedin.com/in/raulkripalani
> > http://blog.raulkr.net | twitter: @raulvk
> >
> > On Mon, Oct 12, 2015 at 5:53 PM, Sergi Vladykin <
> [email protected]>
> > wrote:
> >
> > > In my view we should not pollute sync APIs with all async methods,
> > > definitely we have to separate them
> > > for better UX.
> > >
> > > Currently on Java we have IgniteAsyncSupport with method withAsync()
> > which
> > > returns the same sync API
> > > but that API works in broken manner. Instead it should look like the
> > > following IMO
> > >
> > > interface AsyncSupport<X> {
> > >     X async();
> > > }
> > >
> > > Where X will be an interface with respective async API.  For example
> for
> > > IngneCache we will have AsyncCache
> > > with all the respective async variants of all methods. Like this
> > >
> > > interface IgniteCache<K,V> extends AsyncSupport<AsyncCache<K,V>> {
> > >     V get(K key);
> > > }
> > >
> > >
> > > interface AsyncCache<K,V> {
> > >     IgniteFuture<V> get(K key);
> > > }
> > >
> > > From implementation standpoint both interfaces can be implemented by
> the
> > > same class but for user API
> > > they will be conveniently separated. Implementation of every sync
> method
> > is
> > > trivial if we have
> > > async counterpart: just call get() on received future.
> > >
> > > From documentation point of view we just have to write on each method
> > that
> > > it is a async variant of some
> > > method on main API like following:
> > >
> > >    /**
> > >      * Asynchronous variant of method {@link IgniteCache#get(Object)}.
> > >      */
> > >
> > > This way we will not need to maintain the same docs for all sync and
> > async
> > > methods.
> > >
> > > Sorry, I'm not an expert in .Net but I believe this approach will fit
> > .Net
> > > as well, so it can be consistent across platforms.
> > >
> > > Sergi
> > >
> > >
> > >
> > > 2015-10-12 19:10 GMT+03:00 Dmitriy Setrakyan <[email protected]>:
> > >
> > > > Do I understand correctly that you are suggesting adding "Async(..)"
> > > > counterparts for all the synchronous methods?
> > > >
> > > > Are there any objections about this? If we do it in .NET, then we
> might
> > > as
> > > > well do it in Java, because in my view the same reasoning can be made
> > for
> > > > Java. This will cause significant proliferation of Async methods. For
> > > > example just on IgniteCache API, we will have to add about 40 Async()
> > > > methods.
> > > >
> > > > D.
> > > >
> > > >
> > > >
> > > > On Mon, Oct 12, 2015 at 3:45 AM, Vladimir Ozerov <
> [email protected]
> > >
> > > > wrote:
> > > >
> > > > > No. "await" is actually return from the method immediately. Let me
> > show
> > > > it
> > > > > again:
> > > > >
> > > > > async Task<int> GetAndMultiply() {
> > > > >     Task<int> res =  cache.GetAsync(1);
> > > > >
> > > > >     await res;
> > > > >
> > > > >     return res.Result * res.Result;
> > > > > }
> > > > >
> > > > > maps to the following pseudo-code in Java:
> > > > >
> > > > > Future<Integer> getAndMultiply() {
> > > > >     Future<Integer> res =  cache.getAsync(1);
> > > > >
> > > > >     return res.chain((f) => {
> > > > >         return f.get() * f.get();
> > > > >     });
> > > > > }
> > > > >
> > > > >
> > > > >
> > > > > On Mon, Oct 12, 2015 at 1:36 PM, Yakov Zhdanov <
> [email protected]>
> > > > > wrote:
> > > > >
> > > > > > Is current thread blocked until "await" instruction is completed
> in
> > > > > > parallel thread?
> > > > > >
> > > > > > --Yakov
> > > > > >
> > > > > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[email protected]
> >:
> > > > > >
> > > > > > > Example with Get() operation:
> > > > > > >
> > > > > > > async Task<int> GetAndMultiply() {
> > > > > > >     // This line is executed in current thread.
> > > > > > >     Task<int> res = cache.GetAsync(1);
> > > > > > >
> > > > > > >     await res;
> > > > > > >
> > > > > > >     // This code is executed in another thread when res is
> ready.
> > > > > > >     int mul = res.Result * res.Result;
> > > > > > >
> > > > > > >     return mul;
> > > > > > > }
> > > > > > >
> > > > > > > On Mon, Oct 12, 2015 at 10:12 AM, Dmitriy Setrakyan <
> > > > > > [email protected]
> > > > > > > >
> > > > > > > wrote:
> > > > > > >
> > > > > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > > > > [email protected]
> > > > > > >
> > > > > > > > wrote:
> > > > > > > >
> > > > > > > > > Guys, let's try keeping this topic focused on .Net please,
> > > > because
> > > > > > the
> > > > > > > > > product is not released yet and we can create any API we
> > like.
> > > > > > > > >
> > > > > > > > > Dima, answering your question about async/await - this is
> > > > actually
> > > > > > > native
> > > > > > > > > continuation support in .Net. Consider the following .Net
> > > method:
> > > > > > > > >
> > > > > > > > > async void PutAndPrint() {
> > > > > > > > >     await cache.PutAsync(1, 1);
> > > > > > > > >
> > > > > > > > >     Console.WriteLine("Put value to cache.");
> > > > > > > > > }
> > > > > > > > >
> > > > > > > >
> > > > > > > > And what if the method putAsync would return a value. How
> would
> > > > this
> > > > > > code
> > > > > > > > change?
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>

Reply via email to