Hi Everyone,

I am happy to announce the release of Twig 1.0 featuring Parallel Asynchronous Commands, a fluent command interface and tons of performance enhancing features to really make your applications fly and reduce development time. Twig is an alternative to the standard persistence interfaces JDO and JPA, specifically designed to make the most of the underlying datastore's unique features.

Twig is the only datastore interface that allows you to execute queries and store data in parallel without blocking. If you run 10 queries in a request your app could now run up to 10 times faster!

        // execute a query but don't wait for the results
Future<QueryResultIterator<Band>> futureBands = datastore.find().type(Band.class).returnResultsLater();
        
        // do some other processing or store data while the first command runs
Key key = datastore .store ().instances(myLittlePonies).withParent(bigDaddyPony).returnKeyNow();
        
        // now block until the first command is finished
        Iterator<Band> bands = futureBands.get();
        
Twig is the only interface to support direct unowned relationships so your code is not dependent on low-level datastore classes. It is the only interface to support OR queries by merging together multiple queries, sorting them and filtering out duplicates at the lowest level for performance.

No need to register persistent classes - most objects can be stored with _no_ configuration. Twig is built for speed so it has no start- up overhead and provides many unique performance optimisation features.

Stop wasting time wrestling with JDO! Details, documents and downloads at http://code.google.com/p/twig-persist/

Or read on for a summary of what else Twig can do...



== Persist any Java object graph with no dependencies on the datastore ==

With Twig you store plain Java objects with direct references to each other - just like real Java.

        class MusicFestival
        {
                Date when;
                List<Band> bands;   // Unique to Twig
        }

        class Band
        {
                @Key String name;  // key is optional and can be almost any type
                int performanceFee;
        }

        // create a complex object graph - example taken from the unit tests
        MusicFestival festival = ...

// create an implementation - usually done in a factory or Guice Provider
        ObjectDatastore datastore = new AnnotationObjectDatastore();

        // store the entire object graph of referenced instances
        Key key = datastore.store(festival);

        // find all instances of a type
        Iterator<Band> bands = datastore.find(Band.class);

Band nostalgia = datastore.load(Band.class, "Nostalgia 77"); // load by key

        // delete all bands - time to go home
        datastore.deleteAll(Band.class);
        

== Fluent Interface API ==

Using Twig's fluent interface makes code easier to read and more difficult to make mistakes. http://martinfowler.com/bliki/FluentInterface.html

// store all bands with their record label as parent - notice it knows we will return "keys" Map<Band, Key> keys = datastore.store().instances(bands).withParent(label).returnKeysNow();
        
        // find all bands exploited by EMI - we want results now
        Iterator<Band> exploited = datastore.find()
                .type(Band.class)
                .addFilter("albums.sold", GREATER_THAN, 1000)
                .withAncestor(emi)
                .startFom(15)
                .returnResultsNow();

You can only ever use options that are valid depending on the other options you have set.

Read on to see how "returnResultsLater()" can make your applications faster.


== Polymorphism and Inheritance ==

        RockBand extends Band
        {
                HairStyle hair;
        }
        
        festival.bands.add(ledZeppelin);
        datastore.update(festival);
        
You can store any subtype of Band


== Embedded Collections ==

Say we want to display a list of a bands albums when we display the bands profile page. By embedding the collection of albums in the same entity as the band details we can save a lot of load operations.

        class Band
        {
                @Key String name;
                int performanceFee;
                @Embed Set<Album> albums;  // albums are embedded in the same 
entity
        }

This also means we can query for bands on an albums properties which take multiple queries in JDO and JPA. To find all bands with platinum albums is easy and fast:

        Iterator<Band> popularBands =
                datastore.find()
                        .type(Band.class)
                        .addFilter("albums.sold", GREATER_THAN, 1000000)
                        .returnResultsNow();

== Relationships managed directly ==

No more messing about with Keys and extracting parent keys and creating child keys.

        class Album
        {
                @Key String name;
@Child List<Track> tracks; // all stored as children - also use on single member
        }
        
        class Track
        {
                @Parent Album album;
                @Key String name;
                Duration length;  // most classes can be stored without 
configuration
        }
        
The parent field is automatically set to the parent instance by using the Tracks key. Twig is the only datastore interface that supports these simple direct references


== Parallel Asynchronous Commands ==

Datastore queries can only return contiguous results from an index which forces many useful operators such as OR, IN and NOT_EQUAL to be broken down into multiple queries. Currently these must be executed serially one after the other which slows down you application. Not anymore! Twig 1.0 introduces parallel asynchronous commands which execute at the same time and only block when you need the results.

        // find all tracks from the album but ask for the results in the future
        Future<Iterator<Track>> futureTracks =
                datastore.find()
                        .type(Track.class)
                        .addFilter("duration" GREATER_THAN, 5.0)
                        .returnResultsLater();
        
        // do some other queries and what not...
        
        // now wait for the query to finish and get the results
        Iterator<Track> tracks = futureTracks.get();


Storing data can take a long time and often we just want to return to the user immediately without waiting to see if it was successful.

        // store multiple instances but don't wait
Future<Key> futureKey = datastore.store().instance(aLateArrival).returnKeyLater(); Future<Map<Band, Key>> futureKeys = datastore.store().instances(lotsOfBands).returnKeysLater();
        
Notice that the fluent interface uses generics to know that the result will be Band Keys and that a single instance will return a single Key - return*Key*Later()


== Merged Sorted Queries ==

Handling OR queries yourself and merging the results is difficult especially if the results are sorted. Twig makes it simple to execute multiple queries in parallel and then return you a single iterator.

Here we define two queries which will be merged together - the results will have duplicates filtered out and the sort order will be maintained.

        datastore
                .find()
                .type(Band.class)
.addChildQurey() // creates a new child query that inherits features from its parent
                                .addFilter("albums.sold", GREATER_THAN, 1000000)
.addChlidQuery() // creates a new child query to run in parallel with the first
                                .addFilter("performanceFee", GREATER_THAN, 1000)
.returnResultsNow(); // actually executes in parallel but waits for all queries
                        
This returns all bands that are highly paid OR sold a platinum album. Merged AND queries are not yet supported but will be in a future release.


== High Performance Features ==

Parallel commands and embedded collections go a long way to speed up your application. There are many more performance related features designed to get the most out of your quotas

* Low-level filters: exclude certain Entities or properties of an entity from ever being translated * Shortened Kind name: The name of the kind can be stored many times in your Entities so storing just an abbreviation can save a lot of space * Bulk storeAll() method which also batches together all referenced instances in the same store operation.


== Type Conversion ==

Twig comes with several useful type converters or you can define custom type converters .

        class Band
        {
@Type(Blob.class) Image photo; // convert the image to a blob in the datastore
                ...
        }

== Relational Index Entities ==

Support for Relation Index Entites as described in Bret Slatkin's talk


Lost more features not covered here.  Check it out 
http://code.google.com/p/twig-persist/

John

--
You received this message because you are subscribed to the Google Groups "Google 
App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to