Event processing task

Implemented the new ticker task which processes queued events.
This commit is contained in:
Emmanuel BENOîT 2012-07-01 15:48:37 +02:00
parent af33d44b2a
commit d7b14e3de9
4 changed files with 209 additions and 0 deletions

View file

@ -0,0 +1,113 @@
package com.deepclone.lw.beans.events;
import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
/**
* Events processor component
*
* <p>
* This component acquires the necessary dependencies to create an {@link EventProcessorTask}, does
* so, and registers it with the ticker. It clears the reference to the task when destroyed.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class EventProcessorBean
implements InitializingBean , DisposableBean
{
/** The ticker */
private Ticker ticker;
/** The Spring transaction template */
private TransactionTemplate tTemplate;
/** The database interface */
private DataSource dataSource;
/** The task */
private Runnable task;
/**
* Dependency injector that sets the ticker component
*
* @param ticker
* the ticker component
*/
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
/**
* Dependency injector that sets the transaction manager
*
* <p>
* Creates the transaction template from the transaction manager
*
* @param tManager
* the Spring transaction manager
*/
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
/**
* Dependency injector that sets the database interface
*
* @param dataSource
* the database interface
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dataSource = dataSource;
}
/**
* Initialise and register the event processing task
*
* <p>
* When the component's dependencies have been injected, this method creates the
* {@link EventProcessorTask} instance and registers it to the ticker.
*/
@Override
public void afterPropertiesSet( )
{
this.task = new EventProcessorTask( this.tTemplate , this.dataSource );
this.ticker.registerTask( Frequency.HIGH , "Events processor" , this.task );
}
/**
* Clear the task reference
*
* <p>
* Remove the reference to the {@link EventProcessorTask} instance, allowing the ticker to clean
* up.
*/
@Override
public void destroy( )
{
this.task = null;
}
}

View file

@ -0,0 +1,86 @@
package com.deepclone.lw.beans.events;
import javax.sql.DataSource;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.utils.StoredProc;
/**
* Event processing task
*
* <p>
* This class implements the task responsible for regular database event processing calls. It is
* registered as a high-frequency ticker task by {@link EventProcessorBean}.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class EventProcessorTask
implements Runnable
{
/** The Spring transaction template */
private final TransactionTemplate tTemplate;
/** The stored procedure that implements event processing */
private final StoredProc eqProcess;
/**
* Initialise the transaction template and stored procedure interface
*
* @param tTemplate
* the transaction template
* @param dataSource
* the database interface
*/
public EventProcessorTask( TransactionTemplate tTemplate , DataSource dataSource )
{
this.tTemplate = tTemplate;
this.eqProcess = new StoredProc( dataSource , "events" , "eq_process" );
this.eqProcess.addOutput( "_result" , java.sql.Types.BOOLEAN );
}
/**
* When the task executes, it will call <code>events.eq_process()</code> repeatedly until the
* stored procedure returns <code>false</code>. Each call is made in a separate transaction.
*/
@Override
public void run( )
{
boolean hasMore;
do {
hasMore = this.processBatch( );
} while ( hasMore );
}
/**
* Process a batch of events
*
* <p>
* This method spawns a transaction in which the <code>events.eq_process()</code> stored
* procedure is called.
*
* @return <code>true</code> if events were processed, <code>false</code> if the queues were
* empty.
*/
private boolean processBatch( )
{
return this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
@Override
public Boolean doInTransaction( TransactionStatus status )
{
return (Boolean) EventProcessorTask.this.eqProcess.execute( ).get( "_result" );
}
} );
}
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="eventProcessor" class="com.deepclone.lw.beans.events.EventProcessorBean" />
</beans>

View file

@ -7,6 +7,7 @@
<!-- ========================================================== --> <!-- ========================================================== -->
<!-- Spring configuration loader for all "real" game components --> <!-- Spring configuration loader for all "real" game components -->
<!-- ========================================================== --> <!-- ========================================================== -->
<import resource="game/events.xml" />
<import resource="game/resources.xml" /> <import resource="game/resources.xml" />
<import resource="game/technologies.xml" /> <import resource="game/technologies.xml" />
<import resource="game/updates.xml" /> <import resource="game/updates.xml" />