Skip to content

An OnServers function executes on all servers but only returns the result from one [DATAGEODE-295] #340

Open
@spring-projects-issues

Description

@spring-projects-issues

boglesby opened DATAGEODE-295 and commented

This issue occurs with SBDG 1.2.1.RELEASE and also 1.2.2.RELEASE.

When my boot client executes an OnServers function, I see it executing on all of my servers, but the result the caller gets back contains only 1 server's result instead of the expected collection.

I saw this behavior with the default ResultCollector. If I add a custom ResultCollector, I see addResult being invoked for each server's result. In my custom ResultCollector, the addResult method does a put into a ConcurrentHashMap.

The initial implementation of getResult was returning the ConcurrentHashMap of results, but that failed with a ClassCastException:

java.lang.ClassCastException: java.util.concurrent.ConcurrentHashMap cannot be cast to java.lang.Iterable
        at org.springframework.data.gemfire.function.execution.AbstractFunctionExecution.execute(AbstractFunctionExecution.java:140) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.AbstractFunctionExecution.execute(AbstractFunctionExecution.java:95) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.AbstractFunctionExecution.executeAndExtract(AbstractFunctionExecution.java:158) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate.executeAndExtract(AbstractFunctionTemplate.java:79) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.AbstractFunctionTemplate.executeAndExtract(AbstractFunctionTemplate.java:57) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate.executeAndExtract(GemfireOnServersFunctionTemplate.java:45) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean.invokeFunction(GemfireFunctionProxyFactoryBean.java:102) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean.invoke(GemfireFunctionProxyFactoryBean.java:96) ~[spring-data-geode-2.2.1.RELEASE.jar:2.2.1.RELEASE]

ResultCollector.getResult is not required to return an Iterable in general.

AbstractFunctionExecution.executeAndExtract gets the next element in the Iterable and returns it:

<T> T executeAndExtract() {
  Iterable<T> results = this.execute();
  if (results != null && results.iterator().hasNext()) {
->  Object result = results.iterator().next();
    if (result instanceof Throwable) {
      throw new FunctionException(String.format("Execution of Function %s failed", this.function != null ? this.function.getClass().getName() : String.format("with ID [%s]", this.functionId)), (Throwable)result);
    } else {
      return result;
    }
  } else {
    return null;
  }
}

Any other elements in the Iterable are lost. Is it expecting an Iterable with one element which is the actual result?

If I change getResult in my custom ResultCollector to return a SingletonSet containing the actual result like this, it works:

return Collections.singleton(this.results);

No further details from DATAGEODE-295

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions