I have an update on plans to migrate off the channel APIs.

I looked at both socket.io and sockjs, and neither one of them turned out 
to be acceptable.  socket.io's error handling has some serious issues, and 
sockjs doesn't pass cookies in the connection request (intentionally - they 
claim it's a security hole if anyone does that, but they're making 
assumptions about cookie handling that in my case aren't true).

So here's where I ended up:

- GAE instance continues as usual, for now
- Node.js instance runs a low-level web socket implementation.  I used 
websocket-node, but ws probably would have worked as well.
- Node.js additionally runs a low-level Apple push notification 
implementation
- On the client, which is a hybrid iOS app, I have a native (Objective-C) 
implementation of the web socket client, called SocketRocket. 
 SocketRocket, like socket.io, has some error handling issues, but there's 
no other real option and I was able to work around them.
- The HTML layer then talks to the native layer over a local-http bridge 
(intercepted using NSURLProtocol subclassing, which is a standard trick 
I've used in a bunch of other places)

I used an Objective-C library rather than the UIWebView implementation of 
WebSocket because I'm supporting older iOS devices that don't have 
WebSocket support. However, this tradeoff means that I don't get 
cross-browser support, since many browsers don't have sufficient support 
for WebSockets to connect to the service (websocket-node only supports the 
latest RFC versions of the WebSocket protocol, not earlier Hybi versions).

It all works pretty well.  I now understand why the connection state works 
the way it does in GAE; there is almost certainly a proxy server somewhere 
in GAE land that's holding the channel connection separate from the GAE app 
itself.  However, given that architecture there are a bunch of things that 
the Channel API failed on, which were pretty trivial to deliver in my 
replacement:

- I can send to multiple clients in one request (fan-out)
- I can send multiple messages in one request (batching)
- I can instantly fall back to Apple push notifications if a client is not 
connected (and the message format is the same, so the application level in 
the client doesn't have to care how the message was delivered)
- The request is synchronous so I get a result status back, with individual 
reporting on each client and each message
-- Note though that the result status isn't bulletproof; it just reports 
connection up/down at the time Node.js issues the socket write.  Since the 
socket write is asynchronous, it won't report errors that happen after 
dispatch.  But it's good enough for my purposes.

Some of the tradeoffs I've made mean that the work I've done isn't 
necessarily applicable to another project.  So I'm not planning to post 
this e.g. to github for now.  However, I wanted to post what I've done in 
case others want to pursue a similar path.  The node.js service is only 
about 100 lines of code; most of the tricky bits had to do with shunting 
events around on the client and providing a proper abstraction for 
SocketRocket's error reporting.

Cheers,

- Kris

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-appengine/-/OLnVuy4jr8IJ.
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?hl=en.

Reply via email to