-
Notifications
You must be signed in to change notification settings - Fork 49
Getting started with Sirius
======
The examples below use modified code snippets from our reference applications which implement simple datastores using the Sirius library.
####Implementing a RequestHandler
To use the Sirius library, RequestHandler must be implemented. The RequestHandler has three methods:
- handleGet(String key) - retrieves data from the backend
- handlePut(String key, byte[] body) - updates or creates an item
- handleDelete(String key) - deletes an item
A complex Sirius application will probably have the backend logic separated into other classes, but to keep this example simple the RequestHandler will use a ConcurrentHashMap as the backend implementation. The groovy reference application demonstrates this type of implementation
public class DefaultRequestHandler implements RequestHandler {
private static final String OK = "ok"
ConcurrentHashMap backend = [:]
@Override
public SiriusResult handleGet(String key) {
String value = backend.get(key)
if (value == null) {
println "[$key] does not have a value"
return SiriusResult.none()
}
println "value for [$key] is [$value]"
return SiriusResult.some(value)
}
@Override
public SiriusResult handlePut(String key, byte[] body) {
def value = new String(body)
backend.put(key, value)
println "added value [$value] to backend with key [$key]"
return SiriusResult.some(OK)
}
@Override
public SiriusResult handleDelete(String key) {
def value = backend.remove(key)
if (value) {
println "deleted value [$value] for [$key]"
} else {
println "key [$key] does not exist"
}
return SiriusResult.some(OK)
}
}
The RequestHandler implementation is not used directly, but instead it is inserted into Sirius's workflow for updating and retrieving data from the in-memory datastore. Although Sirius does not require a thread safe backend, in order to safely deal with concurrent backend operations (and avoid ConcurrentModificationException ), it is likely the backend will require some kind of synchronized behaviour. As you can see, Sirius uses a very simple interface for managing a memory based backend. So as long as a backend is maintainable with this interface, an implementor can make the datastore as simple or complex as they need.
####Configuring Sirius
Before booting up Sirius, a SiriusConfiguration needs to be constructed. The simplest SiriusConfiguration would look something like
SiriusConfiguration siriusConfig = new SiriusConfiguration();
siriusConfig.setProp(SiriusConfiguration.HOST(), "localhost");
siriusConfig.setProp(SiriusConfiguration.PORT(), 2552);
siriusConfig.setProp(SiriusConfiguration.CLUSTER_CONFIG(), "/path/to/cluster.config");
siriusConfig.setProp(SiriusConfiguration.LOG_LOCATION(), "/path/to/UberStore");
- host - host of this Sirius / akka node
- port - port of this Sirius / akka node
- cluster config - path to cluster config containing sirius / akka endpoints of all other nodes
- log location - path of directory to store the transaction log
A typical cluster config will look something like
# specify actors in cluster, one per line, as akka addresses
akka.tcp://sirius-2552@localhost:2552/user/sirius
akka.tcp://sirius-2552@localhost:2553/user/sirius
akka.tcp://sirius-2552@localhost:2554/user/sirius
TODO: add link to configuration page
####Running Sirius
Once RequestHandler and
SiriusConfiguration have been
implemented and instantiated, use SiriusFactory.createInstance(RequestHandler requestHandler, SiriusConfig siriusConfig)
to create a
Sirius instance. Before using
Sirius, one should wait until it is online.
To do this, periodically check the isOnline()
method. For example
System.out.println("Waiting for sirius to boot.");
Long waitTime = System.currentTimeMillis() + timeout;
Long sleepTime = 100L;
while (!siriusImpl.isOnline() && System.currentTimeMillis() < waitTime) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// we're the only ones here, nobody's going to interrupt us.
// and if it does happen, well, just keep waiting for sirius to start anyway.
}
}
if (!siriusImpl.isOnline() ) {
throw new IllegalStateException("Sirius failed to boot in " + timeout + "ms");
}
####Using Sirius
Sirius has the following methods
- Future enqueueGet(String key)
- Future enqueuePut(String key, byte[])
- Future enqueueDelete(String key)
- boolean isOnline()
The data operations are very similar to data operations in
RequestHandler. When calling any
data operations, the transaction log is first updated, then appropriate
RequestHandler methods are called
and finally the other nodes in the cluster are updated by forcing them to follow the same workflow. Although used
behind the scenes to ensure consistency, generally enqueueGet(String key)
is not called at the application level.
Instead gets are performed directly against the underlying datastore. The extra serialization steps that Sirius adds
when calling enqueueGet(String key)
to get the same answer are rarely justified.
To see runnable examples, please checkout our reference applications
Copyright 2013-2017 Comcast Cable Communications Management, LLC
Using Sirius
Getting started with Sirius
Configuring Sirius
How to Deploy Sirius
Reference Applications
Migrations and Release Notes
Migration Guide 1.1.x to 1.2.x
Release Notes 2.0.0
Migration Guide 1.2.x to 2.0.x
Developing Sirius
Getting Started
Contributing Guildelines
License
Releasing Sirius
Scaladocs
Test Timeout Failures
Transaction Log
Implementation
Live Compaction
waltool
Other