Hi Stephen Overall, here are my impressions on your proposals:
* -1 to have Client.submitAsync() return a ResultSet instead of a CF * +1 to have ResultSet.all() return a List<Row> * -1 to add a method ResultSet.allAsync() which returns a CF * +0 for the getInt -> asInt rename I think there is value in being async to the network stack. The typical idea for going async is to move the blocking or time consuming operations out of the way as fast as possible. To that extent I think it makes sense to have the entry point (Client.submit()) have an asynchronous version that returns a CompletableFuture. However, I am not sure it is useful to have a ResultSet.allAsync() method that would return a CF, if the entry point (the Client) already offers an asynchronous mode. The only use case it would address would be to be blocked during the network I/O send operation but not during the results retrieval. As for replacing CompletableFuture<ResultSet> with ResultSet, I am not sure it is a good idea. We would lose the chaining capabilities of CompletableFuture, like in the following: client.submitAsync(...).thenApply(MyClass::processResultSet, myExecutor); My understanding is that the ResultSet is an abstraction over a list of rows that may be fetched in background. It is allowed to block if none has yet been fetched. It is not made to compose a chain of callbacks like CompletableFuture does, so it should not replace it. -- Pierre Laporte Performance Engineer www.datastax.com On 2016-02-13 15:40, Stephen Mallette <spmalle...@gmail.com> wrote: > I've been wanting to change something for some time now in Gremlin Driver -> > pretty much since GA, - but it's a breaking change and will make folks have> > to change up their code a bit so I've hesitated. Basically I want to change> > the submit() and submitAsync() API to no longer be async to the network> > stack. I think people find it confusing and it leads to some overly> > verbose. The change would turn signatures like this:> > > public ResultSet submit(final String gremlin)> > CompletableFuture<ResultSet> submitAsync(final String gremlin)> > > into this:> > > public List<Result> submit(final String gremlin)> > public ResultSet submitAsync(final String gremlin)> > > Under this new model, submit() blocks until the entire result is accounted> > for and submitAsync() blocks until the message hits the client side network> > stack and ResultSet behaves like a Future/Iterator as it does now.> > > So rather than:> > > Cluster cluster = Cluster.open();> > Client client = cluster.connect();> > int x = client.submit("1+1").all().get().get(0).getInt();> > int y = client.submitAsync("1+1").get().all().get().get(0).getInt();> > > we have:> > > Cluster cluster = Cluster.open();> > Client client = cluster.connect();> > int x = client.submit("1+1").get(0).getInt();> > int y = client.submitAsync("1+1").all().get().get(0).getInt();> > > While we haven't really reduced the amount of code significantly, a bunch> > of confusion is avoided here because submit() no longer requires the added> > call to all().get() to block until completion.> > > The example is a little dumb because it only returns one Result, in which> > case you would likely do:> > > int x = client.submit("1+1").get(0).getInt();> > int y = client.submitAsync("1+1").one().getInt();> > > Those two calls are functionally equivalent in terms of blocking.> > submitAsync() almost looks nicer in this case. That leads me back to> > all() which returns CompletableFuture<List<Result>>...perhaps that should> > change so that there is both all() and allAsync():> > > public List<Result> all()> > public CompletableFuture<List<Result>> allAsync()> > > In this case, the previous blocking example for all() simplifies to:> > > int y = client.submitAsync("1+1").all().get(0).getInt();> > int y = client.submitAsync("1+1").allAsync().get().get(0).getInt();> > > The same could be done for the some() method. I think the point is here to> > clearly mark for the users which methods are behaving async and which are> > going to block.> > > Finally, I think it would be better to deprecate the get* methods on Result> > in favor of as*. "as" seems to better describe what's happening when those> > methods on Result are called: type coercion and breaks up all the "get"> > looking calls, thus:> > > int y = client.submitAsync("1+1").all().get(0).asInt();> > int y = client.submitAsync("1+1").allAsync().get().get(0).asInt();> > > I'd like to see this change in play for 3.2.0 if possible. Please let me> > know if there are any concerns or better ideas for this API. If there are> > no objections in the next 72 hours (Tuesday, February 16, 2016 at 9:30am> > EST), I'll assume lazy consensus and proceed forward.> > > Thanks,> > > Stephen> >