Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

However, the common case is that the user wants to send a single result, so we should provide a simpler function interface for this case that has a single return value.

 

Function code must exist on the client

The function service API provides a way to invoke functions by id, for example

Code Block
FunctionService.onServer().execute("MY_FUNCTION_ID")

However, internally, we look up the function object itself from the function service in order to read the isHA, optimizeForWrite, and hasResult properties of the function. That means the code must exist on the client and must be registered with the FunctionService.

This is also an opportunity for the user to see an exception if the class on the client does not match the class on the server for these properties.

Lambdas and functions

Lambdas cannot be used for Geode functions, because there are multiple non abstract methods on function like hasResult, isHA, etc.

It would be nice to able to write short functions as lambda expressions, For example

Code Block
FunctionService.onMembers().execute( () -> System.out.println() );

However, that is not possible currently because Function has several non default methods.

We can also get rid of FunctionAdapter in favor of using default methods on Function.

 

Suggested API changes

Instead of a single Function interface, there should be multiple interfaces for different types of functions. TODO - Do we really need VoidFunction (equivalent to hasResult() == false)

Code Block
interface RegionFunction<T> {
  public T execute(RegionFunctionContext context)
}

interface Function<T> {
  public T execute(FunctionContext context)
}

 

RegionFunctionContext should have a method to the local data for the context

Code Block

RegionFunctionContext {
  public Region getLocalData();
}

 

isHA, optimizeForWrite, and hasResult should be removed from Function and should be added to Execution instead

 

ResultCollector should have an addException method

Code Block
public interface ResultCollector<T,S> {
  public void addException(DistributedMember member, Throwable t);
...
}

 

Example of the improved API

Code Block
FunctionService functionService = cache.getFunctionService();

//RegionFunction with a single result
ResultCollector<String, Collection<String>> rc = functionService.onRegion(region)
  .execute(ctx -> ctx.getLocalData().get("key"))
Collection<String> values = rc.getResult()

//RegionFunction without a result, that is optimized for write, but is not HA
functionService.onRegion(region)
  .optimizeForWrite(true)
  .isHA(true)
  .hasResult(false)
  .execute(ctx -> ctx.getLocalData().put("key", "value))