The Talon Manual

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Talon provides an alternative approach to solving this problem, called Environment Replication. With this approach the platform provides an API which allow applications to write HA safe environment providers that capture local decisions on the primary instance into a capture buffer that is replicated along with the inbound message being processed. On the backup instance the capture buffer is then used to playback the same results as were used on the primary thereby allowing the same business logic decisions to be made. Environment providers are fairly simple to write and simple for applications to work with.

For example, Exegy, in partnership with Neeve backed their entire market data api with an environment provider in a matter of days, providing a seamless ultra low latency solution to the market data problem referenced above. With this approach market data is received out band with the respect to the trading application's order processing messages, as . As the primary instance of a trading application looks at current market data while processing messages the values it sees via Exegy's market data apis, the values presented in those calls are captured and replicated to the backup such the the backup instances see the same values when it makes the same api calls. In this fashion the entire stream of market data being absorbed by Exegy need not be replicated to backup instances, just the data that the primary instance uses in making decisions is replicated. 

...

Writing the Environment Provider

Code Block
languagejava
linenumberstrue
package com.neeve.hostnameprovider;
import java.net.*;
import java.nio.ByteBuffer;
import com.neeve.aep.*;
import com.neeve.lang.XString;

/**
 * A simple environment provider that returns the current local host name. 
 */
public class HostNameEnvironmentProvider {
    private final class ProviderImpl implements IAepEnvironmentProvider {
        @Override
        public void setBufferManager(BufferManager bufferManager) {
            HostNameEnvironmentProvider.this.bufferManager = bufferManager;
        }
 
        @Override
        public void onTransactionStart(ByteBuffer buffer, TransactionAction action) {
            HostNameEnvironmentProvider.this.buffer = buffer;
            HostNameEnvironmentProvider.this.action = action;
        }

        @Override
        public void onTransactionEnd() {}

        @Override
        public void close() {}
    }

    // Set by the environment provider impl
    private final ProviderImpl provider = new ProviderImpl();
    private BufferManager bufferManager;
    private TransactionAction action;
    private ByteBuffer buffer;
 
	// stores the local host name
    private final XString localHostName;
    public HostNameEnvironmentProvider() {
        String host = null;
        try {
            host = InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e) {
            host = "unknown";
        }
        localHostName = XString.create(host);
    }
 
    /**
     * Registers the environment provider with the AepEngine.
     *
     * @param engine the engine with which to register. 
     */
    public void register(AepEngine engine) {
        engine.registerEnvironmentProvider(provider);
    }

    /**
     * Looks up the local host name in an HA consistent fashion. 
     *  
     * @param hostName The XString into which to copy the current host name.
     */
    public void getHostNameTo(XString hostName) {
        if (action == TransactionAction.Playback) {
            short len = buffer.getShort();
            hostName.setValue(buffer, buffer.position(), len);
            buffer.position(buffer.position() + len);
        }
        else {
            if (buffer.remaining() < localHostName.getSerializedLength() + 2) {
                buffer = bufferManager.resize(buffer.capacity() * 2);
            }
            // record the value
            buffer.putShort((short)localHostName.getSerializedLength());
            localHostName.copyInto(buffer, buffer.position());
            buffer.position(buffer.position() + localHostName.getSerializedLength());
            // and copy into for the application
            hostName.setValue(localHostName);
        }
    }
}

...