GAEのChannel APIを使ってみたメモ

最近全然触っていなかったGoogle App Engine
今月初旬にリリースした1.4.0からChannel APIというのが使えるようになってリアルタイムWebアプリが出来るらしい、ということなのでちょっと触ってみた。
Channel Python API Overview  |  Python  |  Google Cloud Platform

#!/usr/bin/env python
from google.appengine.api import channel
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp import util


class MainPage(webapp.RequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.create_login_url(self.request.uri))
            return
        
        token = channel.create_channel('hoge')
        template_values = {
            'token': token,
            }
        self.response.out.write(template.render('index.html', template_values))

class PostPage(webapp.RequestHandler):
    def post(self):
        user = users.get_current_user()
        channel.send_message('hoge', self.request.body)
        self.response.out.write('hoge')

class MainHandler(webapp.RequestHandler):
    def get(self):
        self.response.out.write('Hello world!')

def main():
    application = webapp.WSGIApplication([
            ('/', MainHandler),
            ('/mainpage', MainPage),
            ('/post', PostPage),
            ], debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

client_idはとりあえず固定で 指定したURLに繋いでいるものすべてが共通で使うようにしてみた

<html>
  <head>
    <title>Channel API</title>
    <script type="text/javascript" src="/_ah/channel/jsapi"></script>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1.4.4");</script>
    <script type="text/javascript" src="/static/channel.js"></script>
    <link href="/static/style.css" rel="stylesheet" type="text/css"> 
  </head>
  <body>
    <form id="message" action="" method="POST">
      <input id="token" type="hidden" name="token" value="{{ token }}" />
      <input id="text" name="message" type="text" />
      <input type="submit" />
    </form>
    <hr />
    <dl id="list"></dl>
  </body>
</html>

"/_ah/channel/jsapi"ってところにclient側で必要なものが詰まっているようで、サーバー側で生成したtokenを使ってJS側でgoog.appengine.Channelをnewすると、Web Socket的なものが共通なインターフェースで使えるようになるっぽい。

$(function() {
    var token = $('#token').attr('value');

    var sendMessage = function(data) {
        $.ajax({
            url : '/post',
            type: 'POST',
            data: data
        })
    };
    $('#message').submit(function() {
        sendMessage($('#text').attr('value'));
        return false;
    });
    
    channel = new goog.appengine.Channel(token);
    socket = channel.open();
    socket.onopen = function() {
        console.log('open');
    };
    socket.onmessage = function(msg) {
        var date = new Date();
        $('#list').prepend($('<dt>' + date + '</dt><dd>' + msg['data'] + '</dt>'));
    };
    socket.onerror = function() {
        console.log('error');
    };
    socket.onclose = function() {
        console.log('close');
    };
});

POSTされたものをmessageとして送信するようにしてみた。

片方でsubmitしたものがほぼリアルタイムでもう片方で更新される…!

メモ

どうやら、ローカル環境(dev_appserver.py)で動かしているときは1秒ごとにgetしまくっているみたい。本番環境にあげたらそんなことはなかった。web socketを使っているのか comet的なものなのかはよく調べてないので分からない。ブラウザによって切り替えたりしてくれてるのかな…?

実装が悪いだけかもしれないけど、繋がっているはずなのにうまくデータがpushされてこなかったり、ということがあった。

パフォーマンスはどんなもんなんだろう。node.jsとかが面白そうなので触ってみたいけど(まだ触れていない…)、これで十分に出来ること、っていうのもあるのかもしれない。