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 instance in your module. These distributed “foreach” operations can be used to perform bulk updates or removals.
This walkthrough will implement a ForEachApiProcessor for the “MyFirstApiPackage” shopping cart project created in the previous topic.
Prerequisites
.NET 8 SDK or higher.
An API module project with at least one registered API Processor.
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, Evaluate, 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.
using Scaleout.Modules.Abstractions;
namespace MyFirstApiPackage
{
public class RemoveAllEmptyCarts : ForEachApiProcessor<ShoppingCartSossObject>
{
[SossEvalMethod(LockingMode = ApiProcessorLockingMode.None)]
public override ProcessingResult Evaluate(ApiProcessingContext<ShoppingCartSossObject> context,
ShoppingCartSossObject sossObject,
byte[] parameter)
{
if (sossObject.CartItems.Count == 0)
{
return ProcessingResult.Remove;
}
else
{
return ProcessingResult.NoUpdate;
}
}
}
}
The Evaluate implementation must be marked with the
[SossEvalMethod]attribute, indicating whether the supplied SOSS object should be exclusively locked for the duration of the Evaluate call. Use ApiProcessorLockingMode.ExclusiveLock in the[SossEvalMethod]attribute 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 Startup.cs class, find the line in the Configure() method where your API module is registered using ModulePackage.AddApiModule(). The ApiModuleRegistration instance that is returned by this call can be used to add parallel “foreach” operations.
public void Configure(GridConnection gridConnection, ILogger logger, byte[] reservedParam, string packageName)
{
var apiRegistration = _modulePackage.AddApiModule<ShoppingCartSossObject, ShoppingCartApiProcessor>("ShoppingCart");
apiRegistration.AddForeachApiProcessor("RemoveAllEmptyCarts", new RemoveAllEmptyCarts());
}
3. Expose the ForEach operation to clients
In a client application, the ApiModuleClient subclass that was created in the Creating an API Module Client topic can be used to invoke the new RemoveAllEmptyCarts operation. Use the ApiModuleClient.InvokeAllAsync() 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):
// Invoke the "RemoveAllEmptyCarts" parallel ForEach method on the ShoppingCart module.
public Task RemoveAllEmptyCartsAsync()
{
return InvokeAllAsync("RemoveAllEmptyCarts", args: null);
}