Evaluating All Objects in Parallel
API modules can run a custom evaluation method in parallel against all objects in the module. Inherit from ForEachApiProcessor and register your class to perform parallel operations.
Background
Unlike an API Processor endpoint method, which only operates against a single SOSS object at a time, a ForEachApiProcessor implementation runs against every SOSS object instance in your module. These distributed “foreach” operations can be used to perform bulk mutations or removals.
This walkthrough will implement a ForEachApiProcessor for the shopping cart project created in the previous topic.
Prerequisites
Java 8 or higher
Maven
The completed
ShoppingCartAPI module
Procedure
1. Create a ForEachApiProcessor subclass
Create a new class that inherits from the ForEachApiProcessor class. This class will be used to perform bulk removal of empty shopping carts.
The base class takes the type of your API module’s SOSS object as a type parameter. It has a single abstract method, valuate, that must be implemented. This method will be called for every SOSS object in the API module. Clients can supply an arbitrary argument value as a byte array, which is available to the evaluate method as a parameter.
package com.mycompany.shopping.server;
import com.scaleoutsoftware.modules.abstractions.ApiProcessingContext;
import com.scaleoutsoftware.modules.abstractions.ForEachApiProcessor;
import com.scaleoutsoftware.modules.abstractions.ProcessingResult;
public class ShoppingCartForEachApiProcessor extends ForEachApiProcessor<ShoppingCart> {
@Override
public ProcessingResult evaluate(ApiProcessingContext<ShoppingCart> apiProcessingContext, ShoppingCart shoppingCart, byte[] payload) {
if(shoppingCart.isEmpty()) {
return ProcessingResult.Remove;
} else {
return ProcessingResult.NoUpdate;
}
}
}
The evaluate implementation must be marked with the
@SossEvalMethodannotation, indicating whether the supplied SOSS object should be exclusively locked for the duration of the evaluate call. Use ApiProcessorLockingMode.ExclusiveLock in the@SossEvalMethodattribute if you need to ensure that only one request can modify the SOSS object at a time.The evaluate method must return a
ProcessingResultvalue to indicate what should be done with the object in the ScaleOut service after the method has returned:DoUpdate: Indicates that the object was (or may have been) modified and must be updated in the ScaleOut service.
NoUpdate: Indicates the object was not modified and does not need to be updated in the ScaleOut service. (If you are unsure of whether the object was modified, always return DoUpdate.)
Remove: Remove the SOSS object from the ScaleOut service.
2. Register the ForEachApiProcessor implementation
In your API module’s Main.java class, find the line where your API module is registered using ModulePackage.addApiModule(). The ApiModule instance that is returned by this call can be used to add parallel “foreach” operations.
ApiModule<ShoppingCart> apiModule = modulePackage.addApiModule("ShoppingCart", new ShoppingCartApiProcessor(), apiModuleOptions);
apiModule.addForEachOperation("removeEmpty", new ShoppingCartForEachApiProcessor(), new ParallelOperationOptionsBuilder<ShoppingCart, Void>(ShoppingCart.class).build());
3. Expose the ForEach operation to clients
In a client application, the ExampleClient subclass that was created in the Creating an API Module Project topic can be used to invoke the new removeEmpty operation. Use the ApiModuleClient.invokeAll() method to run a parallel operation, supplying the name of the operation and an optional byte array as an argument (not used in this example):
public void removeEmptyCarts() throws ApiModuleException {
invokeAll("removeEmpty", null, Duration.ofSeconds(10));
}