Search code examples
asynchronousnotificationsfuturegridgain

Solution for asynchronous notification upon future completion in GridGain needed


We are evaluating Grid Gain 6.5.5 at the moment as a potential solution for distribution of compute jobs over a grid. The problem we are facing at the moment is a lack of a suitable asynchronous notification mechanism that will notify the sender asynchronously upon job completion (or future completion).

The prototype architecture is relatively simple and the core issue is presented in the pseudo code below (the full code cannot be published due to an NDA). *** Important - the code represents only the "problem", the possible solution in question is described in the text at the bottom together with the question.

//will be used as an entry point to the grid for each client that will submit jobs to the grid
public class GridClient{

//client node for submission that will be reused 
private static Grid gNode = GridGain.start("config xml file goes here");


//provides the functionality of submitting multiple jobs to the grid for calculation
public int sendJobs2Grid(GridJob[] jobs){

    Collection<GridCallable<GridJobOutput>> calls = new ArrayList<>();

    for (final GridJob job : jobs) {

                calls.add(new GridCallable<GridJobOutput>() {
                    @Override public GridJobOutput call() throws Exception {
                        GridJobOutput  result = job.process();
                        return result; 
                    }
                });
        }

        GridFuture<Collection<GridJobOutput>> fut =  this.gNode.compute().call(calls);

        fut.listenAsync(new GridInClosure<GridFuture<Collection<GridJobOutput>>>(){

            @Override public void  apply(GridFuture<Collection<GridJobOutput>> jobsOutputCollection) {

                Collection<GridJobOutput> jobsOutput;

                try {
                    jobsOutput = jobsOutputCollection.get();

                    for(GridJobOutput currResult: jobsOutput){
                        //do something with the current job output BUT CANNOT call jobFinished(GridJobOutput out) method 
                        //of sendJobs2Grid class here
                    }
                } catch (GridException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        return calls.size();
    }


//This function should be invoked asynchronously when the GridFuture is 
//will invoke some processing/aggregation of the result for each submitted job
public void jobFinished(GridJobOutput out) {}

    }

}

//represents a job type that is to be submitted to the grid
public class GridJob{

public GridJobOutput process(){}
}

Description:

The idea is that a GridClient instance will be used to in order to submit a list/array of jobs to the grid, notify the sender how many jobs were submitted and when the jobs are finished (asynchronously) is will perform some processing of the results. For the results processing part the "GridClient.jobFinished(GridJobOutput out)" method should be invoked.

Now getting to question at hand, we are aware of the GridInClosure interface that can be used with "GridFuture.listenAsync(GridInClosure> lsnr)" in order to register a future listener. The problem (if my understanding is correct) is that it is a good and pretty straightforward solution in case the result of the future is to be "processed" by code that is within the scope of the given GridInClosure. In our case we need to use the "GridClient.jobFinished(GridJobOutput out)" which is out of the scope.
Due to the fact that GridInClosure has a single argument R and it has to be of the same type as of GridFuture result it seems impossible to use this approach in a straightforward manner.

If I got it right till now then in order to use "GridFuture.listenAsync(..)" aproach the following has to be done:

  • GridClient will have to implement an interface granting access to the "jobFinished(..)" method let's name it GridJobFinishedListener.
  • GridJob will have to be "wrapped" in new class in order to have an additional property of GridJobFinishedListener type.
  • GridJobOutput will have to be "wrapped" in new class in order to have an addtional property of GridJobFinishedListener type.
  • When the GridJob will be done in addition to the "standard" result GridJobOutput will contain the corresponding GridJobFinishedListener reference.
  • Given the above modifications now GridInClosure can be used now and in the apply(GridJobOutput) method it will be possible to call the GridClient.jobFinished(GridJobOutput out) method through the GridJobFinishedListener interface.

So if till now I got it all right it seems a bit clumsy work around so I hope I have missed something and there is a much better way to handle this relatively simple case of asynchronous call back.

Looking forward to any helpful feedback, thanks a lot in advance.


Solution

  • Your code looks correct and I don't see any problems in calling jobFinished method from the future listener closure. You declared it as an anonymous class which always has a reference to the external class (GridClient in your case), therefore you have access to all variables and methods of GridClient instance.