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

Reply via email to