Skip to content
This repository has been archived by the owner on Feb 22, 2019. It is now read-only.

asynchronous_processing

Pavel Vlasov edited this page Apr 29, 2015 · 1 revision

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.

Clone this wiki locally