-
Notifications
You must be signed in to change notification settings - Fork 10
Home
Tamso is implemented as a set of java libraries for writing and reading your application data, and for consuming configuration. Generally you would host those libraries in services dedicated to consuming input and persisting data, and services dedicated to surfacing the persisted data to applications.
There are maven modules for bootstrapping the libraries into such services, as well as for doing everything in memory in one process. Currently input, output, and configuration in Tasmo are all done via JSON.
Tasmo's basic job is consuming events and maintaining views. You prepare to use tasmo by declaring the events you will send and the views you want to read, so we'll start by explaining events and views.
Briefly, an event represents a change in state to some logical object. It is the unit of input in Tasmo, and it carries with it field value pairs which constitute that state change. These will be different from event to event as different fields of different objects are written. Some attributes are present in all events:
- A unique, time sortable id which identifies the event itself.
- The unique id of the tenant to which this object belongs. Tasmo understands tenancy natively.
- The unique id of the object being modified by the event.
- The logical type of the object.
An event declaration is nothing but a type name, and a set of named and typed fields.
There's only two:
- Literals - this can be any json type. Strings, numbers, booleans, arrays of them, etc. Tasmo treats these as opaque values. What you send in is what you will get back out.
- References - these hold the unique id of one or more other objects. In view declarations, it is through reference fields that you collect data from multiple objects into one view.
You'll notice that a set of event definitions which point to each other via reference fields form a structural graph. This will be important as we go on to talk about views.
A view is what you read back out. It is rooted in one object, but it can contain data from any object that is reachable via any chain of reference fields from the root object. If you think of reference fields as edges of a graph, and literal fields as attributes on the nodes, that's pretty much what's going on.
A view declaration is just a named collection of paths through the structural graph of reference fields of the declared event types. At the tail of each path, you declare what literal fields you want from the object type at that node.
Here is a slightly simplified example event you might send in:
{
"tenant" : "343vvlj3qwslj", <- Tasmo understands tenancy natively, so all events have a tenant id
"eventId" : 425346457, <- here is the event id
"Document" : { <- That is the object type being written
"creationDate" : 1365205250642, <- this is a literal field value
"container" : "Container_1234", <- this is a reference field value. It points to a specific Container object.
"instanceId" : "345908329", <- this is the id of the object
"modificationDate" : 1365205250649,
"subject" : "Very important document",
"body" : "Duck!",
"authors" : ["User_3749", "User_1068", "User_8766"] <- this is a multi-reference field value. It points to an array of User objects.
}
}
Here is an example view you might read out:
{
"objectId" : "Document_345908329", <- this view is rooted on the Document object in the previous event.
"subject" : "Very important document", <- literal fields of that Document
"modificationDate" : 1365205250649,
"container" : { <- this is data pulled from the referenced Container
"objectId" : "Container_1234",
"name" : "HR Documents"
},
“authors” : [ <- this is data pulled from the array of referenced Users
{
"objectId" : "User_3749",
“username” : “mrAwesome”
},
{
"objectId" : "User_1068",
“username” : “ajohnson1200”
},
{
"objectId" : "User_8766",
“username” : “tuckerMatt”
}
]
}
Tasmo depends on some things in the jive-utils repo that aren't yet in maven central. To build everything:
git co https://github.com/jivesoftware/jive-utils.git
git co https://github.com/jivesoftware/tasmo.git
cd jive-utils/code/com/jivesoftware/os/jive-utils
mvn install
cd -
cd tasmo/code/come/jivesoftware/os/tasmo
mvn install
The fastest way to get started with Tasmo is to use the tasmo-local module, which lets you bootstrap both the write and read side components in one process on top of an in-memory datastore.
First we'll define some events and a view. We'll start with something basic: Content and User events. We'll give Content a subject and body field which just hold strings, and an author field that holds a reference to a User. User will just get userName and creationDate fields.
Our view will be rooted on the Content type, and will pull in the Content.subject field, as well as traverse the author reference to pull in the User.userName field;
import com.jivesoftware.os.tasmo.configuration.EventModelParser;
import com.jivesoftware.os.tasmo.configuration.EventsModel;
import com.jivesoftware.os.tasmo.configuration.ViewDefinitionBuilder;
String declarations = "User:userName(value),creationDate(value)|Content:author(ref),subject(value),body(value)";
EventsModel events = new EventModelParser().parse(declarations);
//This constructor takes all the known events, a name for the view, and the name of the root type of the view
ViewDefinitionBuilder viewBuilder = new ViewDefinitionBuilder(events, "SimpleContentView", "Content");
viewBuilder.addPath("Content.subject");
viewBuilder.addPath("Content.author|User.userName);
That's our configuration. Now we'll bootstrap a LocalMaterialization system to read and write data.
import com.jivesoftware.os.tasmo.local.*;
import com.jivesoftware.os.tasmo.id.*;
import com.jivesoftware.os.tasmo.view.reader.api.*;
import com.jivesoftware.os.tasmo.event.api.write.*;
import java.util.*;
List<ViewBinding> viewBindings = new ArrayList<>();
viewBindings.add(viewBuilder.build());
LocalMaterializationSystem localTasmo = new LocalMaterializationSystemBuilder().build(viewBindings);
IdProvider idProvider = localMaterializationSystem.getIdProvider();
TenantId tenantId = new TenantId("booya");
Id actor = Id.NULL;
EventWriter writer = localMaterializationSystem.getWriter();
ViewReader<ViewResponse> reader = localMaterializationSystem.getReader();
//Time to write some events
Event userEvent = EventBuilder.create(idProvider, "User", tenantId, actor).set("userName", "ted").build();
Event contentEvent = EventBuilder.create(idProvider, "Content", tenantId, actor).set("subject", "awesome").
set("body", "awesomer").set("author", userEvent.getObjectId()).build();
writer.write(userEvent, contentEvent);
//And read the generated view
ObjectId viewId = new ObjectId("SimpleContentView", contentEvent.getObjectId());
ViewResponse viewResponse = reader.readView(new ViewDescriptor(tenantId, actor, viewId));