.Net: separate methods for async operations.

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

.Net: separate methods for async operations.

Vladimir Ozerov
Igniters,

Some time ago we decided to merge sync and async methods. E.g. instead of
...

interface Cache<K, V> {
    V get(K key);
    Future<V> getAsync(K key);
}

... we now have:

interface Cache<K, V> extends AsyncSupport {
    V get(K key);
    Cache withAsync();

    Future lastFuture(); // From AsyncSupport, returns future for the last
operation.
}

This approach is questionable. Less methods is good, and all methods go
through JCache API. But async mode became more complex and less usable.
This is especially obvious in Java 8 with its lambdas and CompletableFuture.

In .Net we blindly applied this approach as well. But in this world
AsyncSupport gives even less advantages than in Java:
1) There is no JCache spec here;
2) Core .Net API very often use paired sync and async operations in the
same class near each other - DoMethod(), DoMethodAsync() - and this is what
users normally expect from async-enabled classes.
3) [AsyncSupported] attribute is not highlighted in Visual Studio. The only
way to understand that method supports async mode is to install ReSharper
or to look into source code.
4) .Net has native continuations support with async/await keywords. Our API
doesn't support it well.

Having said that I want to return paired "async" operations to .Net API:
interface ICache<K, V> {
    V Get(K key);
    IFuture<V> GetAsync(K key);
}

It will add 25 new methods to ICache interface and remove 2. But API will
become much more friendly and natural for .Net users.

Any thoughts/objections?

Vladimir.
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Pavel Tupitsyn-3
As a .Net dev, I support this change very much.

Current design with 2 method calls is not easy to use, is error prone, and
is not familiar to .Net crowd:

var cache = ignite.GetCache<int, int>().WithAsync();
var value = cache.Get(1);   // Is it sync or async? Can't tell from code.
In async mode this always returns 0.
var future = cache.GetFuture<int>();   // User has to specify right generic
argument here. Not convenient, error prone, violates design guidelines
var actualValue = await future.ToTask();


As opposed to:
var value = await cache.GetAsync(1).ToTask();

Which is one line, obviously async, with proper generic inference.



On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <[hidden email]>
wrote:

> Igniters,
>
> Some time ago we decided to merge sync and async methods. E.g. instead of
> ...
>
> interface Cache<K, V> {
>     V get(K key);
>     Future<V> getAsync(K key);
> }
>
> ... we now have:
>
> interface Cache<K, V> extends AsyncSupport {
>     V get(K key);
>     Cache withAsync();
>
>     Future lastFuture(); // From AsyncSupport, returns future for the last
> operation.
> }
>
> This approach is questionable. Less methods is good, and all methods go
> through JCache API. But async mode became more complex and less usable.
> This is especially obvious in Java 8 with its lambdas and
> CompletableFuture.
>
> In .Net we blindly applied this approach as well. But in this world
> AsyncSupport gives even less advantages than in Java:
> 1) There is no JCache spec here;
> 2) Core .Net API very often use paired sync and async operations in the
> same class near each other - DoMethod(), DoMethodAsync() - and this is what
> users normally expect from async-enabled classes.
> 3) [AsyncSupported] attribute is not highlighted in Visual Studio. The only
> way to understand that method supports async mode is to install ReSharper
> or to look into source code.
> 4) .Net has native continuations support with async/await keywords. Our API
> doesn't support it well.
>
> Having said that I want to return paired "async" operations to .Net API:
> interface ICache<K, V> {
>     V Get(K key);
>     IFuture<V> GetAsync(K key);
> }
>
> It will add 25 new methods to ICache interface and remove 2. But API will
> become much more friendly and natural for .Net users.
>
> Any thoughts/objections?
>
> Vladimir.
>



--
--
Pavel Tupitsyn
GridGain Systems, Inc.
www.gridgain.com
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
I don't think I like the proposed change.

First of all, from my experience, the async APIs are used a lot less than
sync ones, so having 2 lines of code for async calls is not a big deal in
my view.

Secondly, the scope of this change would be huge. We would have to double
our Compute, Cache, Services, and many other APIs. Seems to me like a huge
amount of effort for a very questionable benefit, if any at all. One can
argue, for example, that so many duplicate sync/async methods on all the
APIs is more confusing, not less.

And lastly, I am against having .NET APIs different from Java APIs. We
should have API parity as much as possible between all the platforms, and
especially the .NET one, where we provide so many features.

On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <[hidden email]>
wrote:

> As a .Net dev, I support this change very much.
>
> Current design with 2 method calls is not easy to use, is error prone, and
> is not familiar to .Net crowd:
>
> var cache = ignite.GetCache<int, int>().WithAsync();
> var value = cache.Get(1);   // Is it sync or async? Can't tell from code.

In async mode this always returns 0.
>

Yes, you are right. But then again, async documentation clearly says that
you should get a future to get the actual asynchronous result.

The proper code here is:
-----------
var cache = ignite.GetCache<int, int>().WithAsync();

// Line #1
cache.Get(1);

// Line #2
cache.Future().Get();
-----------

2 lines of code instead of one is not a big deal in my view.


> var future = cache.GetFuture<int>();   // User has to specify right generic
> argument here. Not convenient, error prone, violates design guidelines
> var actualValue = await future.ToTask();
>
>
> As opposed to:
> var value = await cache.GetAsync(1).ToTask();



>
> Which is one line, obviously async, with proper generic inference.
>
>
>
> On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <[hidden email]>
> wrote:
>
> > Igniters,
> >
> > Some time ago we decided to merge sync and async methods. E.g. instead of
> > ...
> >
> > interface Cache<K, V> {
> >     V get(K key);
> >     Future<V> getAsync(K key);
> > }
> >
> > ... we now have:
> >
> > interface Cache<K, V> extends AsyncSupport {
> >     V get(K key);
> >     Cache withAsync();
> >
> >     Future lastFuture(); // From AsyncSupport, returns future for the
> last
> > operation.
> > }
> >
> > This approach is questionable. Less methods is good, and all methods go
> > through JCache API. But async mode became more complex and less usable.
> > This is especially obvious in Java 8 with its lambdas and
> > CompletableFuture.
> >
> > In .Net we blindly applied this approach as well. But in this world
> > AsyncSupport gives even less advantages than in Java:
> > 1) There is no JCache spec here;
> > 2) Core .Net API very often use paired sync and async operations in the
> > same class near each other - DoMethod(), DoMethodAsync() - and this is
> what
> > users normally expect from async-enabled classes.
> > 3) [AsyncSupported] attribute is not highlighted in Visual Studio. The
> only
> > way to understand that method supports async mode is to install ReSharper
> > or to look into source code.
> > 4) .Net has native continuations support with async/await keywords. Our
> API
> > doesn't support it well.
> >
> > Having said that I want to return paired "async" operations to .Net API:
> > interface ICache<K, V> {
> >     V Get(K key);
> >     IFuture<V> GetAsync(K key);
> > }
> >
> > It will add 25 new methods to ICache interface and remove 2. But API will
> > become much more friendly and natural for .Net users.
> >
> > Any thoughts/objections?
> >
> > Vladimir.
> >
>
>
>
> --
> --
> Pavel Tupitsyn
> GridGain Systems, Inc.
> www.gridgain.com
>
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Pavel Tupitsyn-3
Hi Dmitry,

> First of all, from my experience, the async APIs are used a lot less than sync
ones

This may be true, especially if the API is clunky.
But .NET has async/await functionality which makes async code a lot cleaner
and easier.
Good async/await support is very important, because it does not block
current thread, which in turn is important for high load applications.
All modern .NET APIs are async.


> Secondly, the scope of this change would be huge.

I don't think so. There are around 40 methods with async support in current
Ignite.NET.
Adding their async counterparts will take a couple of hours at most.
And it will simplify interop code somewhat because GetFuture goes away.


> And lastly, I am against having .NET APIs different from Java APIs.

Functionally they will be the same. But we should not try to bring Java
semantics to .NET.
Async methods in .NET are "T DoSomething()" + "Task<T> DoSomethingAsync()"
and we should follow this pattern so our API looks familiar to .NET
community.


> // Line #2
> cache.Future().Get();

It is cache.GetFuture<X>(). Pay attention to "X". This is very important:
user has to specify correct return type according to return type of
operation on "Line 1".
Very annoying and error prone. There is even a style-checker warning about
such things.


> 2 lines of code instead of one is not a big deal in my view.

It is 2 times too much, sometimes even more. Imagine a situation where you
need to perform multiple async operations:

cache.Get(1);
var res = await cache.GetFuture<int>().ToTask();

compute.Call(new MyCallable(res))
var res2 = await compute.GetFuture<string>().ToTask()


And with proper async API it can even be a one-liner.
var res2 = await compute.CallAsync(new MyCallable(await cache.GetAsync(1)));


API is the first thing a programmer sees in the new product. Let's do it
right.

Thanks,

On Fri, Oct 9, 2015 at 7:17 PM, Dmitriy Setrakyan <[hidden email]>
wrote:

> I don't think I like the proposed change.
>
> First of all, from my experience, the async APIs are used a lot less than
> sync ones, so having 2 lines of code for async calls is not a big deal in
> my view.
>
> Secondly, the scope of this change would be huge. We would have to double
> our Compute, Cache, Services, and many other APIs. Seems to me like a huge
> amount of effort for a very questionable benefit, if any at all. One can
> argue, for example, that so many duplicate sync/async methods on all the
> APIs is more confusing, not less.
>
> And lastly, I am against having .NET APIs different from Java APIs. We
> should have API parity as much as possible between all the platforms, and
> especially the .NET one, where we provide so many features.
>
> On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <[hidden email]>
> wrote:
>
> > As a .Net dev, I support this change very much.
> >
> > Current design with 2 method calls is not easy to use, is error prone,
> and
> > is not familiar to .Net crowd:
> >
> > var cache = ignite.GetCache<int, int>().WithAsync();
> > var value = cache.Get(1);   // Is it sync or async? Can't tell from code.
>
> In async mode this always returns 0.
> >
>
> Yes, you are right. But then again, async documentation clearly says that
> you should get a future to get the actual asynchronous result.
>
> The proper code here is:
> -----------
> var cache = ignite.GetCache<int, int>().WithAsync();
>
> // Line #1
> cache.Get(1);
>
> // Line #2
> cache.Future().Get();
> -----------
>
> 2 lines of code instead of one is not a big deal in my view.
>
>
> > var future = cache.GetFuture<int>();   // User has to specify right
> generic
> > argument here. Not convenient, error prone, violates design guidelines
> > var actualValue = await future.ToTask();
> >
> >
> > As opposed to:
> > var value = await cache.GetAsync(1).ToTask();
>
>
>
> >
> > Which is one line, obviously async, with proper generic inference.
> >
> >
> >
> > On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <[hidden email]>
> > wrote:
> >
> > > Igniters,
> > >
> > > Some time ago we decided to merge sync and async methods. E.g. instead
> of
> > > ...
> > >
> > > interface Cache<K, V> {
> > >     V get(K key);
> > >     Future<V> getAsync(K key);
> > > }
> > >
> > > ... we now have:
> > >
> > > interface Cache<K, V> extends AsyncSupport {
> > >     V get(K key);
> > >     Cache withAsync();
> > >
> > >     Future lastFuture(); // From AsyncSupport, returns future for the
> > last
> > > operation.
> > > }
> > >
> > > This approach is questionable. Less methods is good, and all methods go
> > > through JCache API. But async mode became more complex and less usable.
> > > This is especially obvious in Java 8 with its lambdas and
> > > CompletableFuture.
> > >
> > > In .Net we blindly applied this approach as well. But in this world
> > > AsyncSupport gives even less advantages than in Java:
> > > 1) There is no JCache spec here;
> > > 2) Core .Net API very often use paired sync and async operations in the
> > > same class near each other - DoMethod(), DoMethodAsync() - and this is
> > what
> > > users normally expect from async-enabled classes.
> > > 3) [AsyncSupported] attribute is not highlighted in Visual Studio. The
> > only
> > > way to understand that method supports async mode is to install
> ReSharper
> > > or to look into source code.
> > > 4) .Net has native continuations support with async/await keywords. Our
> > API
> > > doesn't support it well.
> > >
> > > Having said that I want to return paired "async" operations to .Net
> API:
> > > interface ICache<K, V> {
> > >     V Get(K key);
> > >     IFuture<V> GetAsync(K key);
> > > }
> > >
> > > It will add 25 new methods to ICache interface and remove 2. But API
> will
> > > become much more friendly and natural for .Net users.
> > >
> > > Any thoughts/objections?
> > >
> > > Vladimir.
> > >
> >
> >
> >
> > --
> > --
> > Pavel Tupitsyn
> > GridGain Systems, Inc.
> > www.gridgain.com
> >
>



--
--
Pavel Tupitsyn
GridGain Systems, Inc.
www.gridgain.com
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
Pavel, can you explain how .NET async semantics are different from Java?

On Fri, Oct 9, 2015 at 1:46 PM, Pavel Tupitsyn <[hidden email]>
wrote:

> Hi Dmitry,
>
> > First of all, from my experience, the async APIs are used a lot less
> than sync
> ones
>
> This may be true, especially if the API is clunky.
> But .NET has async/await functionality which makes async code a lot cleaner
> and easier.
> Good async/await support is very important, because it does not block
> current thread, which in turn is important for high load applications.
> All modern .NET APIs are async.
>
>
> > Secondly, the scope of this change would be huge.
>
> I don't think so. There are around 40 methods with async support in current
> Ignite.NET.
> Adding their async counterparts will take a couple of hours at most.
> And it will simplify interop code somewhat because GetFuture goes away.
>
>
> > And lastly, I am against having .NET APIs different from Java APIs.
>
> Functionally they will be the same. But we should not try to bring Java
> semantics to .NET.
> Async methods in .NET are "T DoSomething()" + "Task<T> DoSomethingAsync()"
> and we should follow this pattern so our API looks familiar to .NET
> community.
>
>
> > // Line #2
> > cache.Future().Get();
>
> It is cache.GetFuture<X>(). Pay attention to "X". This is very important:
> user has to specify correct return type according to return type of
> operation on "Line 1".
> Very annoying and error prone. There is even a style-checker warning about
> such things.
>
>
> > 2 lines of code instead of one is not a big deal in my view.
>
> It is 2 times too much, sometimes even more. Imagine a situation where you
> need to perform multiple async operations:
>
> cache.Get(1);
> var res = await cache.GetFuture<int>().ToTask();
>
> compute.Call(new MyCallable(res))
> var res2 = await compute.GetFuture<string>().ToTask()
>
>
> And with proper async API it can even be a one-liner.
> var res2 = await compute.CallAsync(new MyCallable(await
> cache.GetAsync(1)));
>
>
> API is the first thing a programmer sees in the new product. Let's do it
> right.
>
> Thanks,
>
> On Fri, Oct 9, 2015 at 7:17 PM, Dmitriy Setrakyan <[hidden email]>
> wrote:
>
> > I don't think I like the proposed change.
> >
> > First of all, from my experience, the async APIs are used a lot less than
> > sync ones, so having 2 lines of code for async calls is not a big deal in
> > my view.
> >
> > Secondly, the scope of this change would be huge. We would have to double
> > our Compute, Cache, Services, and many other APIs. Seems to me like a
> huge
> > amount of effort for a very questionable benefit, if any at all. One can
> > argue, for example, that so many duplicate sync/async methods on all the
> > APIs is more confusing, not less.
> >
> > And lastly, I am against having .NET APIs different from Java APIs. We
> > should have API parity as much as possible between all the platforms, and
> > especially the .NET one, where we provide so many features.
> >
> > On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <[hidden email]>
> > wrote:
> >
> > > As a .Net dev, I support this change very much.
> > >
> > > Current design with 2 method calls is not easy to use, is error prone,
> > and
> > > is not familiar to .Net crowd:
> > >
> > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > var value = cache.Get(1);   // Is it sync or async? Can't tell from
> code.
> >
> > In async mode this always returns 0.
> > >
> >
> > Yes, you are right. But then again, async documentation clearly says that
> > you should get a future to get the actual asynchronous result.
> >
> > The proper code here is:
> > -----------
> > var cache = ignite.GetCache<int, int>().WithAsync();
> >
> > // Line #1
> > cache.Get(1);
> >
> > // Line #2
> > cache.Future().Get();
> > -----------
> >
> > 2 lines of code instead of one is not a big deal in my view.
> >
> >
> > > var future = cache.GetFuture<int>();   // User has to specify right
> > generic
> > > argument here. Not convenient, error prone, violates design guidelines
> > > var actualValue = await future.ToTask();
> > >
> > >
> > > As opposed to:
> > > var value = await cache.GetAsync(1).ToTask();
> >
> >
> >
> > >
> > > Which is one line, obviously async, with proper generic inference.
> > >
> > >
> > >
> > > On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <[hidden email]>
> > > wrote:
> > >
> > > > Igniters,
> > > >
> > > > Some time ago we decided to merge sync and async methods. E.g.
> instead
> > of
> > > > ...
> > > >
> > > > interface Cache<K, V> {
> > > >     V get(K key);
> > > >     Future<V> getAsync(K key);
> > > > }
> > > >
> > > > ... we now have:
> > > >
> > > > interface Cache<K, V> extends AsyncSupport {
> > > >     V get(K key);
> > > >     Cache withAsync();
> > > >
> > > >     Future lastFuture(); // From AsyncSupport, returns future for the
> > > last
> > > > operation.
> > > > }
> > > >
> > > > This approach is questionable. Less methods is good, and all methods
> go
> > > > through JCache API. But async mode became more complex and less
> usable.
> > > > This is especially obvious in Java 8 with its lambdas and
> > > > CompletableFuture.
> > > >
> > > > In .Net we blindly applied this approach as well. But in this world
> > > > AsyncSupport gives even less advantages than in Java:
> > > > 1) There is no JCache spec here;
> > > > 2) Core .Net API very often use paired sync and async operations in
> the
> > > > same class near each other - DoMethod(), DoMethodAsync() - and this
> is
> > > what
> > > > users normally expect from async-enabled classes.
> > > > 3) [AsyncSupported] attribute is not highlighted in Visual Studio.
> The
> > > only
> > > > way to understand that method supports async mode is to install
> > ReSharper
> > > > or to look into source code.
> > > > 4) .Net has native continuations support with async/await keywords.
> Our
> > > API
> > > > doesn't support it well.
> > > >
> > > > Having said that I want to return paired "async" operations to .Net
> > API:
> > > > interface ICache<K, V> {
> > > >     V Get(K key);
> > > >     IFuture<V> GetAsync(K key);
> > > > }
> > > >
> > > > It will add 25 new methods to ICache interface and remove 2. But API
> > will
> > > > become much more friendly and natural for .Net users.
> > > >
> > > > Any thoughts/objections?
> > > >
> > > > Vladimir.
> > > >
> > >
> > >
> > >
> > > --
> > > --
> > > Pavel Tupitsyn
> > > GridGain Systems, Inc.
> > > www.gridgain.com
> > >
> >
>
>
>
> --
> --
> Pavel Tupitsyn
> GridGain Systems, Inc.
> www.gridgain.com
>
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Sergi
I think IgniteAsyncSupport is a big piece of crap even in java, sync/async
API separation definitely must be done in another way.

Sergi

2015-10-10 0:40 GMT+03:00 Dmitriy Setrakyan <[hidden email]>:

> Pavel, can you explain how .NET async semantics are different from Java?
>
> On Fri, Oct 9, 2015 at 1:46 PM, Pavel Tupitsyn <[hidden email]>
> wrote:
>
> > Hi Dmitry,
> >
> > > First of all, from my experience, the async APIs are used a lot less
> > than sync
> > ones
> >
> > This may be true, especially if the API is clunky.
> > But .NET has async/await functionality which makes async code a lot
> cleaner
> > and easier.
> > Good async/await support is very important, because it does not block
> > current thread, which in turn is important for high load applications.
> > All modern .NET APIs are async.
> >
> >
> > > Secondly, the scope of this change would be huge.
> >
> > I don't think so. There are around 40 methods with async support in
> current
> > Ignite.NET.
> > Adding their async counterparts will take a couple of hours at most.
> > And it will simplify interop code somewhat because GetFuture goes away.
> >
> >
> > > And lastly, I am against having .NET APIs different from Java APIs.
> >
> > Functionally they will be the same. But we should not try to bring Java
> > semantics to .NET.
> > Async methods in .NET are "T DoSomething()" + "Task<T>
> DoSomethingAsync()"
> > and we should follow this pattern so our API looks familiar to .NET
> > community.
> >
> >
> > > // Line #2
> > > cache.Future().Get();
> >
> > It is cache.GetFuture<X>(). Pay attention to "X". This is very important:
> > user has to specify correct return type according to return type of
> > operation on "Line 1".
> > Very annoying and error prone. There is even a style-checker warning
> about
> > such things.
> >
> >
> > > 2 lines of code instead of one is not a big deal in my view.
> >
> > It is 2 times too much, sometimes even more. Imagine a situation where
> you
> > need to perform multiple async operations:
> >
> > cache.Get(1);
> > var res = await cache.GetFuture<int>().ToTask();
> >
> > compute.Call(new MyCallable(res))
> > var res2 = await compute.GetFuture<string>().ToTask()
> >
> >
> > And with proper async API it can even be a one-liner.
> > var res2 = await compute.CallAsync(new MyCallable(await
> > cache.GetAsync(1)));
> >
> >
> > API is the first thing a programmer sees in the new product. Let's do it
> > right.
> >
> > Thanks,
> >
> > On Fri, Oct 9, 2015 at 7:17 PM, Dmitriy Setrakyan <[hidden email]
> >
> > wrote:
> >
> > > I don't think I like the proposed change.
> > >
> > > First of all, from my experience, the async APIs are used a lot less
> than
> > > sync ones, so having 2 lines of code for async calls is not a big deal
> in
> > > my view.
> > >
> > > Secondly, the scope of this change would be huge. We would have to
> double
> > > our Compute, Cache, Services, and many other APIs. Seems to me like a
> > huge
> > > amount of effort for a very questionable benefit, if any at all. One
> can
> > > argue, for example, that so many duplicate sync/async methods on all
> the
> > > APIs is more confusing, not less.
> > >
> > > And lastly, I am against having .NET APIs different from Java APIs. We
> > > should have API parity as much as possible between all the platforms,
> and
> > > especially the .NET one, where we provide so many features.
> > >
> > > On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <[hidden email]
> >
> > > wrote:
> > >
> > > > As a .Net dev, I support this change very much.
> > > >
> > > > Current design with 2 method calls is not easy to use, is error
> prone,
> > > and
> > > > is not familiar to .Net crowd:
> > > >
> > > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > > var value = cache.Get(1);   // Is it sync or async? Can't tell from
> > code.
> > >
> > > In async mode this always returns 0.
> > > >
> > >
> > > Yes, you are right. But then again, async documentation clearly says
> that
> > > you should get a future to get the actual asynchronous result.
> > >
> > > The proper code here is:
> > > -----------
> > > var cache = ignite.GetCache<int, int>().WithAsync();
> > >
> > > // Line #1
> > > cache.Get(1);
> > >
> > > // Line #2
> > > cache.Future().Get();
> > > -----------
> > >
> > > 2 lines of code instead of one is not a big deal in my view.
> > >
> > >
> > > > var future = cache.GetFuture<int>();   // User has to specify right
> > > generic
> > > > argument here. Not convenient, error prone, violates design
> guidelines
> > > > var actualValue = await future.ToTask();
> > > >
> > > >
> > > > As opposed to:
> > > > var value = await cache.GetAsync(1).ToTask();
> > >
> > >
> > >
> > > >
> > > > Which is one line, obviously async, with proper generic inference.
> > > >
> > > >
> > > >
> > > > On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <
> [hidden email]>
> > > > wrote:
> > > >
> > > > > Igniters,
> > > > >
> > > > > Some time ago we decided to merge sync and async methods. E.g.
> > instead
> > > of
> > > > > ...
> > > > >
> > > > > interface Cache<K, V> {
> > > > >     V get(K key);
> > > > >     Future<V> getAsync(K key);
> > > > > }
> > > > >
> > > > > ... we now have:
> > > > >
> > > > > interface Cache<K, V> extends AsyncSupport {
> > > > >     V get(K key);
> > > > >     Cache withAsync();
> > > > >
> > > > >     Future lastFuture(); // From AsyncSupport, returns future for
> the
> > > > last
> > > > > operation.
> > > > > }
> > > > >
> > > > > This approach is questionable. Less methods is good, and all
> methods
> > go
> > > > > through JCache API. But async mode became more complex and less
> > usable.
> > > > > This is especially obvious in Java 8 with its lambdas and
> > > > > CompletableFuture.
> > > > >
> > > > > In .Net we blindly applied this approach as well. But in this world
> > > > > AsyncSupport gives even less advantages than in Java:
> > > > > 1) There is no JCache spec here;
> > > > > 2) Core .Net API very often use paired sync and async operations in
> > the
> > > > > same class near each other - DoMethod(), DoMethodAsync() - and this
> > is
> > > > what
> > > > > users normally expect from async-enabled classes.
> > > > > 3) [AsyncSupported] attribute is not highlighted in Visual Studio.
> > The
> > > > only
> > > > > way to understand that method supports async mode is to install
> > > ReSharper
> > > > > or to look into source code.
> > > > > 4) .Net has native continuations support with async/await keywords.
> > Our
> > > > API
> > > > > doesn't support it well.
> > > > >
> > > > > Having said that I want to return paired "async" operations to .Net
> > > API:
> > > > > interface ICache<K, V> {
> > > > >     V Get(K key);
> > > > >     IFuture<V> GetAsync(K key);
> > > > > }
> > > > >
> > > > > It will add 25 new methods to ICache interface and remove 2. But
> API
> > > will
> > > > > become much more friendly and natural for .Net users.
> > > > >
> > > > > Any thoughts/objections?
> > > > >
> > > > > Vladimir.
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > --
> > > > Pavel Tupitsyn
> > > > GridGain Systems, Inc.
> > > > www.gridgain.com
> > > >
> > >
> >
> >
> >
> > --
> > --
> > Pavel Tupitsyn
> > GridGain Systems, Inc.
> > www.gridgain.com
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

nivanov
I was one of few people who reviewed this design originally and didn't see
much problem with it (it did seem contrived a bit). I now actually agree
with "below" sentiment that in retrospect it was a very bad decision and
APIs is frankly unusable IMHO.

The minute you pass instance of cache elsewhere on the call chain - this
API cannot be used sanely.

Java vs. .NET, ​API parity vs. feature parity are all good discussions to
have - but at least Java side needs to be fixed.​
--
Nikita Ivanov


On Sat, Oct 10, 2015 at 2:39 AM, Sergi Vladykin <[hidden email]>
wrote:

> I think IgniteAsyncSupport is a big piece of crap even in java, sync/async
> API separation definitely must be done in another way.
>
> Sergi
>
> 2015-10-10 0:40 GMT+03:00 Dmitriy Setrakyan <[hidden email]>:
>
> > Pavel, can you explain how .NET async semantics are different from Java?
> >
> > On Fri, Oct 9, 2015 at 1:46 PM, Pavel Tupitsyn <[hidden email]>
> > wrote:
> >
> > > Hi Dmitry,
> > >
> > > > First of all, from my experience, the async APIs are used a lot less
> > > than sync
> > > ones
> > >
> > > This may be true, especially if the API is clunky.
> > > But .NET has async/await functionality which makes async code a lot
> > cleaner
> > > and easier.
> > > Good async/await support is very important, because it does not block
> > > current thread, which in turn is important for high load applications.
> > > All modern .NET APIs are async.
> > >
> > >
> > > > Secondly, the scope of this change would be huge.
> > >
> > > I don't think so. There are around 40 methods with async support in
> > current
> > > Ignite.NET.
> > > Adding their async counterparts will take a couple of hours at most.
> > > And it will simplify interop code somewhat because GetFuture goes away.
> > >
> > >
> > > > And lastly, I am against having .NET APIs different from Java APIs.
> > >
> > > Functionally they will be the same. But we should not try to bring Java
> > > semantics to .NET.
> > > Async methods in .NET are "T DoSomething()" + "Task<T>
> > DoSomethingAsync()"
> > > and we should follow this pattern so our API looks familiar to .NET
> > > community.
> > >
> > >
> > > > // Line #2
> > > > cache.Future().Get();
> > >
> > > It is cache.GetFuture<X>(). Pay attention to "X". This is very
> important:
> > > user has to specify correct return type according to return type of
> > > operation on "Line 1".
> > > Very annoying and error prone. There is even a style-checker warning
> > about
> > > such things.
> > >
> > >
> > > > 2 lines of code instead of one is not a big deal in my view.
> > >
> > > It is 2 times too much, sometimes even more. Imagine a situation where
> > you
> > > need to perform multiple async operations:
> > >
> > > cache.Get(1);
> > > var res = await cache.GetFuture<int>().ToTask();
> > >
> > > compute.Call(new MyCallable(res))
> > > var res2 = await compute.GetFuture<string>().ToTask()
> > >
> > >
> > > And with proper async API it can even be a one-liner.
> > > var res2 = await compute.CallAsync(new MyCallable(await
> > > cache.GetAsync(1)));
> > >
> > >
> > > API is the first thing a programmer sees in the new product. Let's do
> it
> > > right.
> > >
> > > Thanks,
> > >
> > > On Fri, Oct 9, 2015 at 7:17 PM, Dmitriy Setrakyan <
> [hidden email]
> > >
> > > wrote:
> > >
> > > > I don't think I like the proposed change.
> > > >
> > > > First of all, from my experience, the async APIs are used a lot less
> > than
> > > > sync ones, so having 2 lines of code for async calls is not a big
> deal
> > in
> > > > my view.
> > > >
> > > > Secondly, the scope of this change would be huge. We would have to
> > double
> > > > our Compute, Cache, Services, and many other APIs. Seems to me like a
> > > huge
> > > > amount of effort for a very questionable benefit, if any at all. One
> > can
> > > > argue, for example, that so many duplicate sync/async methods on all
> > the
> > > > APIs is more confusing, not less.
> > > >
> > > > And lastly, I am against having .NET APIs different from Java APIs.
> We
> > > > should have API parity as much as possible between all the platforms,
> > and
> > > > especially the .NET one, where we provide so many features.
> > > >
> > > > On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <
> [hidden email]
> > >
> > > > wrote:
> > > >
> > > > > As a .Net dev, I support this change very much.
> > > > >
> > > > > Current design with 2 method calls is not easy to use, is error
> > prone,
> > > > and
> > > > > is not familiar to .Net crowd:
> > > > >
> > > > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > > > var value = cache.Get(1);   // Is it sync or async? Can't tell from
> > > code.
> > > >
> > > > In async mode this always returns 0.
> > > > >
> > > >
> > > > Yes, you are right. But then again, async documentation clearly says
> > that
> > > > you should get a future to get the actual asynchronous result.
> > > >
> > > > The proper code here is:
> > > > -----------
> > > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > >
> > > > // Line #1
> > > > cache.Get(1);
> > > >
> > > > // Line #2
> > > > cache.Future().Get();
> > > > -----------
> > > >
> > > > 2 lines of code instead of one is not a big deal in my view.
> > > >
> > > >
> > > > > var future = cache.GetFuture<int>();   // User has to specify right
> > > > generic
> > > > > argument here. Not convenient, error prone, violates design
> > guidelines
> > > > > var actualValue = await future.ToTask();
> > > > >
> > > > >
> > > > > As opposed to:
> > > > > var value = await cache.GetAsync(1).ToTask();
> > > >
> > > >
> > > >
> > > > >
> > > > > Which is one line, obviously async, with proper generic inference.
> > > > >
> > > > >
> > > > >
> > > > > On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <
> > [hidden email]>
> > > > > wrote:
> > > > >
> > > > > > Igniters,
> > > > > >
> > > > > > Some time ago we decided to merge sync and async methods. E.g.
> > > instead
> > > > of
> > > > > > ...
> > > > > >
> > > > > > interface Cache<K, V> {
> > > > > >     V get(K key);
> > > > > >     Future<V> getAsync(K key);
> > > > > > }
> > > > > >
> > > > > > ... we now have:
> > > > > >
> > > > > > interface Cache<K, V> extends AsyncSupport {
> > > > > >     V get(K key);
> > > > > >     Cache withAsync();
> > > > > >
> > > > > >     Future lastFuture(); // From AsyncSupport, returns future for
> > the
> > > > > last
> > > > > > operation.
> > > > > > }
> > > > > >
> > > > > > This approach is questionable. Less methods is good, and all
> > methods
> > > go
> > > > > > through JCache API. But async mode became more complex and less
> > > usable.
> > > > > > This is especially obvious in Java 8 with its lambdas and
> > > > > > CompletableFuture.
> > > > > >
> > > > > > In .Net we blindly applied this approach as well. But in this
> world
> > > > > > AsyncSupport gives even less advantages than in Java:
> > > > > > 1) There is no JCache spec here;
> > > > > > 2) Core .Net API very often use paired sync and async operations
> in
> > > the
> > > > > > same class near each other - DoMethod(), DoMethodAsync() - and
> this
> > > is
> > > > > what
> > > > > > users normally expect from async-enabled classes.
> > > > > > 3) [AsyncSupported] attribute is not highlighted in Visual
> Studio.
> > > The
> > > > > only
> > > > > > way to understand that method supports async mode is to install
> > > > ReSharper
> > > > > > or to look into source code.
> > > > > > 4) .Net has native continuations support with async/await
> keywords.
> > > Our
> > > > > API
> > > > > > doesn't support it well.
> > > > > >
> > > > > > Having said that I want to return paired "async" operations to
> .Net
> > > > API:
> > > > > > interface ICache<K, V> {
> > > > > >     V Get(K key);
> > > > > >     IFuture<V> GetAsync(K key);
> > > > > > }
> > > > > >
> > > > > > It will add 25 new methods to ICache interface and remove 2. But
> > API
> > > > will
> > > > > > become much more friendly and natural for .Net users.
> > > > > >
> > > > > > Any thoughts/objections?
> > > > > >
> > > > > > Vladimir.
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > --
> > > > > Pavel Tupitsyn
> > > > > GridGain Systems, Inc.
> > > > > www.gridgain.com
> > > > >
> > > >
> > >
> > >
> > >
> > > --
> > > --
> > > Pavel Tupitsyn
> > > GridGain Systems, Inc.
> > > www.gridgain.com
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Vladimir Ozerov
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.");
}

In Java it maps to somewhat like this (not strict, but idea is the same):

IgniteFuture getAndPrint() {
    cache.put(1, 1);

    return cache.future().chain((f) => {
        System.out.println("Put value to cache.");
    });
}

I.e. in .Net you can write asynchronous code as if it was synchronous - no
explicit callbacks or closures.

.Net platform has completely different view of how and when async
operations should be used. They invested quite a few efforts to develop
vertically integrated threading framework for this. It starts on low WinAPI
level and ends up with Task/async/await concepts on user API level. This
framework is not friendly for 3rd-party products like Ignite and can be
normally used only inside Windows environment. But it covers the needs of
the majority of use cases and is widely accepted by .Net community.

We simply cannot ignore these integral .Net concepts when developing API.

On Sun, Oct 11, 2015 at 7:52 AM, Nikita Ivanov <[hidden email]> wrote:

> I was one of few people who reviewed this design originally and didn't see
> much problem with it (it did seem contrived a bit). I now actually agree
> with "below" sentiment that in retrospect it was a very bad decision and
> APIs is frankly unusable IMHO.
>
> The minute you pass instance of cache elsewhere on the call chain - this
> API cannot be used sanely.
>
> Java vs. .NET, ​API parity vs. feature parity are all good discussions to
> have - but at least Java side needs to be fixed.​
> --
> Nikita Ivanov
>
>
> On Sat, Oct 10, 2015 at 2:39 AM, Sergi Vladykin <[hidden email]>
> wrote:
>
> > I think IgniteAsyncSupport is a big piece of crap even in java,
> sync/async
> > API separation definitely must be done in another way.
> >
> > Sergi
> >
> > 2015-10-10 0:40 GMT+03:00 Dmitriy Setrakyan <[hidden email]>:
> >
> > > Pavel, can you explain how .NET async semantics are different from
> Java?
> > >
> > > On Fri, Oct 9, 2015 at 1:46 PM, Pavel Tupitsyn <[hidden email]
> >
> > > wrote:
> > >
> > > > Hi Dmitry,
> > > >
> > > > > First of all, from my experience, the async APIs are used a lot
> less
> > > > than sync
> > > > ones
> > > >
> > > > This may be true, especially if the API is clunky.
> > > > But .NET has async/await functionality which makes async code a lot
> > > cleaner
> > > > and easier.
> > > > Good async/await support is very important, because it does not block
> > > > current thread, which in turn is important for high load
> applications.
> > > > All modern .NET APIs are async.
> > > >
> > > >
> > > > > Secondly, the scope of this change would be huge.
> > > >
> > > > I don't think so. There are around 40 methods with async support in
> > > current
> > > > Ignite.NET.
> > > > Adding their async counterparts will take a couple of hours at most.
> > > > And it will simplify interop code somewhat because GetFuture goes
> away.
> > > >
> > > >
> > > > > And lastly, I am against having .NET APIs different from Java APIs.
> > > >
> > > > Functionally they will be the same. But we should not try to bring
> Java
> > > > semantics to .NET.
> > > > Async methods in .NET are "T DoSomething()" + "Task<T>
> > > DoSomethingAsync()"
> > > > and we should follow this pattern so our API looks familiar to .NET
> > > > community.
> > > >
> > > >
> > > > > // Line #2
> > > > > cache.Future().Get();
> > > >
> > > > It is cache.GetFuture<X>(). Pay attention to "X". This is very
> > important:
> > > > user has to specify correct return type according to return type of
> > > > operation on "Line 1".
> > > > Very annoying and error prone. There is even a style-checker warning
> > > about
> > > > such things.
> > > >
> > > >
> > > > > 2 lines of code instead of one is not a big deal in my view.
> > > >
> > > > It is 2 times too much, sometimes even more. Imagine a situation
> where
> > > you
> > > > need to perform multiple async operations:
> > > >
> > > > cache.Get(1);
> > > > var res = await cache.GetFuture<int>().ToTask();
> > > >
> > > > compute.Call(new MyCallable(res))
> > > > var res2 = await compute.GetFuture<string>().ToTask()
> > > >
> > > >
> > > > And with proper async API it can even be a one-liner.
> > > > var res2 = await compute.CallAsync(new MyCallable(await
> > > > cache.GetAsync(1)));
> > > >
> > > >
> > > > API is the first thing a programmer sees in the new product. Let's do
> > it
> > > > right.
> > > >
> > > > Thanks,
> > > >
> > > > On Fri, Oct 9, 2015 at 7:17 PM, Dmitriy Setrakyan <
> > [hidden email]
> > > >
> > > > wrote:
> > > >
> > > > > I don't think I like the proposed change.
> > > > >
> > > > > First of all, from my experience, the async APIs are used a lot
> less
> > > than
> > > > > sync ones, so having 2 lines of code for async calls is not a big
> > deal
> > > in
> > > > > my view.
> > > > >
> > > > > Secondly, the scope of this change would be huge. We would have to
> > > double
> > > > > our Compute, Cache, Services, and many other APIs. Seems to me
> like a
> > > > huge
> > > > > amount of effort for a very questionable benefit, if any at all.
> One
> > > can
> > > > > argue, for example, that so many duplicate sync/async methods on
> all
> > > the
> > > > > APIs is more confusing, not less.
> > > > >
> > > > > And lastly, I am against having .NET APIs different from Java APIs.
> > We
> > > > > should have API parity as much as possible between all the
> platforms,
> > > and
> > > > > especially the .NET one, where we provide so many features.
> > > > >
> > > > > On Fri, Oct 9, 2015 at 7:05 AM, Pavel Tupitsyn <
> > [hidden email]
> > > >
> > > > > wrote:
> > > > >
> > > > > > As a .Net dev, I support this change very much.
> > > > > >
> > > > > > Current design with 2 method calls is not easy to use, is error
> > > prone,
> > > > > and
> > > > > > is not familiar to .Net crowd:
> > > > > >
> > > > > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > > > > var value = cache.Get(1);   // Is it sync or async? Can't tell
> from
> > > > code.
> > > > >
> > > > > In async mode this always returns 0.
> > > > > >
> > > > >
> > > > > Yes, you are right. But then again, async documentation clearly
> says
> > > that
> > > > > you should get a future to get the actual asynchronous result.
> > > > >
> > > > > The proper code here is:
> > > > > -----------
> > > > > var cache = ignite.GetCache<int, int>().WithAsync();
> > > > >
> > > > > // Line #1
> > > > > cache.Get(1);
> > > > >
> > > > > // Line #2
> > > > > cache.Future().Get();
> > > > > -----------
> > > > >
> > > > > 2 lines of code instead of one is not a big deal in my view.
> > > > >
> > > > >
> > > > > > var future = cache.GetFuture<int>();   // User has to specify
> right
> > > > > generic
> > > > > > argument here. Not convenient, error prone, violates design
> > > guidelines
> > > > > > var actualValue = await future.ToTask();
> > > > > >
> > > > > >
> > > > > > As opposed to:
> > > > > > var value = await cache.GetAsync(1).ToTask();
> > > > >
> > > > >
> > > > >
> > > > > >
> > > > > > Which is one line, obviously async, with proper generic
> inference.
> > > > > >
> > > > > >
> > > > > >
> > > > > > On Fri, Oct 9, 2015 at 4:47 PM, Vladimir Ozerov <
> > > [hidden email]>
> > > > > > wrote:
> > > > > >
> > > > > > > Igniters,
> > > > > > >
> > > > > > > Some time ago we decided to merge sync and async methods. E.g.
> > > > instead
> > > > > of
> > > > > > > ...
> > > > > > >
> > > > > > > interface Cache<K, V> {
> > > > > > >     V get(K key);
> > > > > > >     Future<V> getAsync(K key);
> > > > > > > }
> > > > > > >
> > > > > > > ... we now have:
> > > > > > >
> > > > > > > interface Cache<K, V> extends AsyncSupport {
> > > > > > >     V get(K key);
> > > > > > >     Cache withAsync();
> > > > > > >
> > > > > > >     Future lastFuture(); // From AsyncSupport, returns future
> for
> > > the
> > > > > > last
> > > > > > > operation.
> > > > > > > }
> > > > > > >
> > > > > > > This approach is questionable. Less methods is good, and all
> > > methods
> > > > go
> > > > > > > through JCache API. But async mode became more complex and less
> > > > usable.
> > > > > > > This is especially obvious in Java 8 with its lambdas and
> > > > > > > CompletableFuture.
> > > > > > >
> > > > > > > In .Net we blindly applied this approach as well. But in this
> > world
> > > > > > > AsyncSupport gives even less advantages than in Java:
> > > > > > > 1) There is no JCache spec here;
> > > > > > > 2) Core .Net API very often use paired sync and async
> operations
> > in
> > > > the
> > > > > > > same class near each other - DoMethod(), DoMethodAsync() - and
> > this
> > > > is
> > > > > > what
> > > > > > > users normally expect from async-enabled classes.
> > > > > > > 3) [AsyncSupported] attribute is not highlighted in Visual
> > Studio.
> > > > The
> > > > > > only
> > > > > > > way to understand that method supports async mode is to install
> > > > > ReSharper
> > > > > > > or to look into source code.
> > > > > > > 4) .Net has native continuations support with async/await
> > keywords.
> > > > Our
> > > > > > API
> > > > > > > doesn't support it well.
> > > > > > >
> > > > > > > Having said that I want to return paired "async" operations to
> > .Net
> > > > > API:
> > > > > > > interface ICache<K, V> {
> > > > > > >     V Get(K key);
> > > > > > >     IFuture<V> GetAsync(K key);
> > > > > > > }
> > > > > > >
> > > > > > > It will add 25 new methods to ICache interface and remove 2.
> But
> > > API
> > > > > will
> > > > > > > become much more friendly and natural for .Net users.
> > > > > > >
> > > > > > > Any thoughts/objections?
> > > > > > >
> > > > > > > Vladimir.
> > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > --
> > > > > > Pavel Tupitsyn
> > > > > > GridGain Systems, Inc.
> > > > > > www.gridgain.com
> > > > > >
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > --
> > > > Pavel Tupitsyn
> > > > GridGain Systems, Inc.
> > > > www.gridgain.com
> > > >
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <[hidden email]>
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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Vladimir Ozerov
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 <[hidden email]>
wrote:

> On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <[hidden email]>
> 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

yzhdanov
Is current thread blocked until "await" instruction is completed in
parallel thread?

--Yakov

2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:

> 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 <[hidden email]
> >
> wrote:
>
> > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <[hidden email]>
> > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

yzhdanov
In reply to this post by Pavel Tupitsyn-3
> 2 lines of code instead of one is not a big deal in my view.

>It is 2 times too much, sometimes even more. Imagine a situation where you
>need to perform multiple async operations:

>cache.Get(1);
>var res = await cache.GetFuture<int>().ToTask();

>compute.Call(new MyCallable(res))
>var res2 = await compute.GetFuture<string>().ToTask()


>And with proper async API it can even be a one-liner.
>var res2 = await compute.CallAsync(new MyCallable(await
cache.GetAsync(1)));

It seems that this example does not show the proper usecase for async APIs.
If it is reimplemented in sync manner it would become clearer and,
probably, faster. What is the purpose of async here if I wait in current
thread?

--Yakov
Reply | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Vladimir Ozerov
In reply to this post by yzhdanov
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 <[hidden email]> wrote:

> Is current thread blocked until "await" instruction is completed in
> parallel thread?
>
> --Yakov
>
> 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
>
> > 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 <
> [hidden email]
> > >
> > wrote:
> >
> > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <[hidden email]
> >
> > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
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 <[hidden email]>
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 <[hidden email]>
> wrote:
>
> > Is current thread blocked until "await" instruction is completed in
> > parallel thread?
> >
> > --Yakov
> >
> > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> >
> > > 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 <
> > [hidden email]
> > > >
> > > wrote:
> > >
> > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> [hidden email]
> > >
> > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Vladimir Ozerov
Well, as I mentioned before, paired "Async()" methods are very natural to
.Net. When Microsoft creates new API it usually contains such sync/async
pairs.

I am not sure we should do the same thing in Java only because we are going
to do this in .Net. There must be other strong reasons.

On Mon, Oct 12, 2015 at 7:10 PM, Dmitriy Setrakyan <[hidden email]>
wrote:

> 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 <[hidden email]>
> 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 <[hidden email]>
> > wrote:
> >
> > > Is current thread blocked until "await" instruction is completed in
> > > parallel thread?
> > >
> > > --Yakov
> > >
> > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > >
> > > > 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 <
> > > [hidden email]
> > > > >
> > > > wrote:
> > > >
> > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > [hidden email]
> > > >
> > > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Sergi
In reply to this post by dsetrakyan
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 <[hidden email]>:

> 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 <[hidden email]>
> 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 <[hidden email]>
> > wrote:
> >
> > > Is current thread blocked until "await" instruction is completed in
> > > parallel thread?
> > >
> > > --Yakov
> > >
> > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > >
> > > > 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 <
> > > [hidden email]
> > > > >
> > > > wrote:
> > > >
> > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > [hidden email]
> > > >
> > > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
I think I like Sergey's idea. Any way to make it backward compatible?

On Mon, Oct 12, 2015 at 9:53 AM, Sergi Vladykin <[hidden email]>
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 <[hidden email]>:
>
> > 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 <[hidden email]>
> > 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 <[hidden email]>
> > > wrote:
> > >
> > > > Is current thread blocked until "await" instruction is completed in
> > > > parallel thread?
> > > >
> > > > --Yakov
> > > >
> > > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > > >
> > > > > 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 <
> > > > [hidden email]
> > > > > >
> > > > > wrote:
> > > > >
> > > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > > [hidden email]
> > > > >
> > > > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Vladimir Ozerov
In reply to this post by Sergi
Sergi,

Pavel and I thought about this. The problem with this approach is that not
all methods are async. E.g. name(), lock(K), iterator(), etc.. So you
should either mix sync and async methods in AsyncCache still, or expose
only async methods. In the latter case we will require backwards
transformation: IgniteCache AsyncCache.sync().

Looks like there is no ideal solutions. We should just pick one.

Also please note that IgniteCache.get() != AsyncCache.get().get(). Sync and
async operations do not go through the same path in general case. Otherwise
sync operations could be blocked by async operations due to exhausted
semaphore. We found a deadlock in IGFS because of this several days ago.

Consistency between platforms should have minimal priority. .Net and Java
are very different. For example we cannot even have "V Get(K)" method in
.Net cache. Instead we have "V TryGet(K, out bool)" because .Net supports
structs and have full generics support and naive Java approach simply
doesn't work here. Base concepts must be the same across platforms, but
methods signatures and grouping will be different.




On Mon, Oct 12, 2015 at 7:53 PM, Sergi Vladykin <[hidden email]>
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 <[hidden email]>:
>
> > 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 <[hidden email]>
> > 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 <[hidden email]>
> > > wrote:
> > >
> > > > Is current thread blocked until "await" instruction is completed in
> > > > parallel thread?
> > > >
> > > > --Yakov
> > > >
> > > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > > >
> > > > > 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 <
> > > > [hidden email]
> > > > > >
> > > > > wrote:
> > > > >
> > > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > > [hidden email]
> > > > >
> > > > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

dsetrakyan
On Mon, Oct 12, 2015 at 10:15 AM, Vladimir Ozerov <[hidden email]>
wrote:


> The problem with this approach is that not all methods are async. E.g.
> name(), lock(K), iterator(), etc.. So you should either mix sync and async
> methods in AsyncCache still, or expose only async methods.


I think AsyncCache, or rather CacheAsync, should expose only async methods.
Moreover, should IgniteCache simply extend CacheAsync API?


> In the latter case we will require backwards
> transformation: IgniteCache AsyncCache.sync().
>

Not sure this is needed.


> Consistency between platforms should have minimal priority. .Net and Java
> are very different. For example we cannot even have "V Get(K)" method in
> .Net cache. Instead we have "V TryGet(K, out bool)" because .Net supports
> structs and have full generics support and naive Java approach simply
> doesn't work here. Base concepts must be the same across platforms, but
> methods signatures and grouping will be different.
>

I disagree here. I think consistency matters. Moreover, based on the
previous .NET examples you have provided, I do not see much difference
between .NET and Java, other than different syntax. I think the same
CacheAsync design can be applied to both.


>
>
>
> On Mon, Oct 12, 2015 at 7:53 PM, Sergi Vladykin <[hidden email]>
> 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 <[hidden email]>:
> >
> > > 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 <[hidden email]
> >
> > > 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 <[hidden email]>
> > > > wrote:
> > > >
> > > > > Is current thread blocked until "await" instruction is completed in
> > > > > parallel thread?
> > > > >
> > > > > --Yakov
> > > > >
> > > > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > > > >
> > > > > > 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 <
> > > > > [hidden email]
> > > > > > >
> > > > > > wrote:
> > > > > >
> > > > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > > > [hidden email]
> > > > > >
> > > > > > > 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 | Threaded
Open this post in threaded view
|

Re: .Net: separate methods for async operations.

Sergi
In reply to this post by Vladimir Ozerov
Vladimir,

I don't see why it is an issue that not all Cache methods will have async
variants,
AsyncCache just will have only needed async methods.

Also I don't see why we need backward transformation from async to sync,
as a user you should always pass IgniteCache everywhere and
use async as needed like *cache.async().get("myKey")*.

I agree that IgniteCache.get() != AsyncCache.get().get(), I was a bit too
optimistic
about it, but it is not a show stopper as well, just a bit more efforts
will be needed.
Anyways these sync and async implementations will follow the same patterns
all the time.

As for platforms consistency I'm for it where it makes sense, but I believe
you know better :)

Sergi

2015-10-12 20:15 GMT+03:00 Vladimir Ozerov <[hidden email]>:

> Sergi,
>
> Pavel and I thought about this. The problem with this approach is that not
> all methods are async. E.g. name(), lock(K), iterator(), etc.. So you
> should either mix sync and async methods in AsyncCache still, or expose
> only async methods. In the latter case we will require backwards
> transformation: IgniteCache AsyncCache.sync().
>
> Looks like there is no ideal solutions. We should just pick one.
>
> Also please note that IgniteCache.get() != AsyncCache.get().get(). Sync and
> async operations do not go through the same path in general case. Otherwise
> sync operations could be blocked by async operations due to exhausted
> semaphore. We found a deadlock in IGFS because of this several days ago.
>
> Consistency between platforms should have minimal priority. .Net and Java
> are very different. For example we cannot even have "V Get(K)" method in
> .Net cache. Instead we have "V TryGet(K, out bool)" because .Net supports
> structs and have full generics support and naive Java approach simply
> doesn't work here. Base concepts must be the same across platforms, but
> methods signatures and grouping will be different.
>
>
>
>
> On Mon, Oct 12, 2015 at 7:53 PM, Sergi Vladykin <[hidden email]>
> 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 <[hidden email]>:
> >
> > > 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 <[hidden email]
> >
> > > 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 <[hidden email]>
> > > > wrote:
> > > >
> > > > > Is current thread blocked until "await" instruction is completed in
> > > > > parallel thread?
> > > > >
> > > > > --Yakov
> > > > >
> > > > > 2015-10-12 10:41 GMT+03:00 Vladimir Ozerov <[hidden email]>:
> > > > >
> > > > > > 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 <
> > > > > [hidden email]
> > > > > > >
> > > > > > wrote:
> > > > > >
> > > > > > > On Sun, Oct 11, 2015 at 3:42 AM, Vladimir Ozerov <
> > > > [hidden email]
> > > > > >
> > > > > > > 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?
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>
12