-
Notifications
You must be signed in to change notification settings - Fork 4
asynchronous_processing
NFS provides several bundles for asynchronous processing which store state in the model repository and as such asynchronous processes can survive a JVM restart, e.g. a task can be scheduled to be executed in a week from the moment of scheduling and during this time the JVM may be restarted multiple times.
This bundle provides means of persisting regular Java objects to a CDO respository, it "boxes" them into CDOObjects. It is leveraged by other asynchronous bundles. Developers shall use BoxUtil
box()
and unbox()
methods. Additional box classes can be added by creating a EClass which implements Box interface, and creating and registering a converter - see sources for more details.
Scheduler API is similar to Java ExecutorService API, but commands are stored in the model repository and are executed in their own CDO transaction.
To add scheduler to your application define a scheduler provider/adapter component as shown below:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" immediate="true" name="Scheduler Provider">
<implementation class="org.nasdanika.cdo.scheduler.ResourceTaskContainerSchedulerProviderComponent"/>
<service>
<provide interface="org.nasdanika.cdo.scheduler.SchedulerProvider"/>
<provide interface="org.nasdanika.core.AdapterProvider"/>
<provide interface="org.nasdanika.cdo.CDOSessionInitializer"/>
</service>
<reference
bind="setTransactionContextProvider"
cardinality="1..1"
interface="org.nasdanika.cdo.CDOTransactionContextProvider"
name="CDOTransactionContextProvider"
policy="static"/>
</scr:component>
Scheduler is obtained from SchedulerProvider by code operating out of CDOTransactionContext and by adapting context otherwise. The code snippet
below shows two methods - test()
method is activated by an HTTP request. It creates an object method function linked to invokeMe()
method of
the same object. Then it binds value 66.8
to function's argument and schedules the function to be executed in 3 seconds.
invokeMe()
is called by the scheduler, the first parameter is annotated with @ContextParameter
annotation and therefore
the transaction context is passed through it as an argument. 66.8
converted to String
is passed through the arg
parameter.
@RouteMethod
@SuppressWarnings("unchecked")
public String test(@ContextParameter HttpContext context) throws Exception {
CDOTransactionContext<LoginPasswordCredentials> cdoContext = context.adapt(CDOTransactionContext.class);
Principal principal = cdoContext.getPrincipal();
System.out.println("In test method "+principal.cdoID());
Scheduler<LoginPasswordCredentials, CDOObject> scheduler = context.adapt(Scheduler.class);
CDOFunctionFactory<LoginPasswordCredentials> functionFactory = new CDOFunctionFactory<LoginPasswordCredentials>(cdoContext, principal);
CDOTransactionContextFunction<LoginPasswordCredentials, Object, Object> command = functionFactory.createObjectMethodFunction(this, "invokeMe", CDOTransactionContext.class, String.class);
CDOObject task = scheduler.schedule(command.bind(cdoContext, 66.8), 3, TimeUnit.SECONDS);
return String.valueOf(task);
}
public void invokeMe(@ContextParameter CDOTransactionContext<LoginPasswordCredentials> context, String arg) {
System.out.println("I was invoked : "+arg+" in a context of "+context);
}
This bundle allows to create functions which can invoke OSGi service method, Java object method, or JavaScript. Functions support binding of arguments and can be persisted in the model repository.
Persistent promises API inspired by Kris Kowal's Q. Persistent promises simplify development of long-running processes, e.g. (pseudo-code)
Approver bob = ... // get approver service.
Promise approvalPromise = bob.sendRequest(requestToProvisionACloudVM);
approvalPromise.then(provisionCommand, notifyRequestorCommand);
In the code snippet above Bob may approve or reject the request several days after the request was submitted. During this time the JVM may be restarted, but the promise and "then" commands are persisted in the repository and therefore survive JVM restarts.