An example of this Google App Engine push implementation is available at http://gdsgaepush.appspot.com, once again with admin/admin or user/user. If you open two browsers on the application, the changes made on from side should be also updated on the other. The eclipse project can be downloaded here.
The GAE environment is very interesting because it is fully clustered: each request can be unpredictably handled by a different server instance. The only reliable way to communicate between different requests/users is by using the datastore or memcache (or a combination of both). In a first messaging implementation, we have chosen the memcache API that allows fast communication between processes and is easy to use. The main drawback is that it is not a reliable store and that client subscriptions or messages could be lost under high memory usage, but for non critical use it might be acceptable.
The implementation is relatively simple: Gravity subscriptions and channels are stored in the cache with a configurable expiration delay. Each channel maintains its current number of pending messages in the cache. Publisher threads just increment this number and store new messages in the cache, and subscriber threads poll the channel counter at regular intervals and get existing messages from the cache when there are available. The poller thread by default polls the channel every 500ms and has a total duration of 20s (under the 30s limit of GAE).
It's important to note that due to the use of memcache, only serializable objects can be sent in Gravity messages (but it's also the case with JMS). Besides that simple limitation, all features of Gravity (client <-> client, server -> client, selectors, ...) can be used with GAE (see documentation here).
The configuration of the GAE provider can be done as follows :
<servlet>
<servlet-name>GravityServlet</servlet-name>
<servlet-class>org.granite.gravity.gae.GravityGAEServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>GravityServlet</servlet-name>
<url-pattern>/gravityamf/*</url-pattern>
</servlet-mapping>
<gravity
factory="org.granite.gravity.gae.GAEGravityFactory
channel-idle-timeout-millis="1800000">
<configuration>
<gae polling-interval="500">
</configuration>
</gravity>
<service id="gravity-service"
class="flex.messaging.services.MessagingService"
messageTypes="flex.messaging.messages.AsyncMessage">
<adapters>
<adapter-definition id="gae" class="org.granite.gravity.gae.GAEServiceAdapter"/>
</adapters>
<destination id="exampleDestination">
<channels>
<channel ref="my-gravityamf"/>
</channels>
<adapter ref="gae"/>
</destination>
</services>
This new server push provider complements the current existing support for AMF remoting and JDO persistence and makes GraniteDS 2.0 a complete platform for deploying Flex applications on Google App Engine.
As always, feedback and comments are welcome.