Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App Engine Python Modules and channel service

I am using App Engine Modules in my python project. (https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads)

I am also using channels in m project: https://developers.google.com/appengine/docs/python/channel/

I want to direct the connected/disconnected post messages ('/_ah/channel/connected/', '/_ah/channel/disconnected/') to my api module. Right now I can't get them to show up in any module (default or api)

app.yaml

    api_version: 1
    application: integrate
    version: 1-0-0
    runtime: python27
    threadsafe: true

    builtins:
      - deferred: on

    libraries:
      - name: pycrypto
      version: "2.6"

    handlers:
      - url: /favicon\.ico
      static_files: static/favicon.ico
      upload: static/favicon\.ico

      - url: /admin/.+
      script: src.default.main.app
      login: admin

      - url: /.*
      script: src.default.main.app

api.yaml

    api_version: 1
    application: integrate
    module: api
    version: 1-0-0
    runtime: python27
    threadsafe: true

    inbound_services:
      - channel_presence

    builtins:
      - deferred: on

    libraries:
      - name: pycrypto
      version: "2.6"

    handlers:
      - url: /admin/.+
      script: src.api.main.app
      login: admin

      - url: /.*
      script: src.api.main.app

dispatch.yaml

    application: integrate

    dispatch:
       - url: "*/_ah/channel/*"
       module: api

Note: Just to be clear this all works in dev mode locally.

api.main.app

    app = webapp2.WSGIApplication(debug=True)
    _routes = [
        :
        ChannelDisconnectedHandler.mapping(),
        ChannelConnectHandler.mapping()
    ]

    for r in self._routes:
        app.router.add(r)

ChannelDisconnectHandler

    CHANNEL_DISCONNECTED_URL_PATTERN = '/_ah/channel/disconnected/'


    class ChannelDisconnectedHandler(RequestHandler):

        @classmethod
        def mapping(cls):
            return CHANNEL_DISCONNECTED_URL_PATTERN, cls

        def post(self):
            """
            Channel Presence handler. Will be called when a client disconnects.
            """
            channel_id = self.request.get('from')
            logging.info("Channel Disconnect. Id: %s" % channel_id)

ChannelConnectHandler

    CHANNEL_CONNECT_URL_PATTERN = '/_ah/channel/connected/'

    class ChannelConnectHandler(RequestHandler):

        @classmethod
        def mapping(cls):
            return CHANNEL_CONNECT_URL_PATTERN, cls

        def post(self):
            """
            Channel Presence handler. Will be called when a client connects.
            """
            channel_id = self.request.get('from')
            logging.info("Channel Connect. Id: %s" % channel_id)

So my client (written in javascript) posts to my api module and opens a channel.

    var open_channel = function(tokenResponse) {
        console.log("Open Channel. token Response: " + tokenResponse)
        token = tokenResponse.token;
        var channel = new goog.appengine.Channel(token);
        if (socket != null) {
            socket.close();
        }
        socket = channel.open();
        socket.onopen = onOpened;
        socket.onmessage = onMessage;
        socket.onerror = onError;
        socket.onclose = onClose;
    };

    onOpened = function() {
        console.info("Channel API Connection is open.");
    };

    onError = function(e) {
        console.info("CHANNEL Error. Code: " + e.code + ", Description: " + e.description);
    };

    onClose = function() {
        console.info("Close Channel");
    };

    onMessage = function(msg) {
       console.info("Message Received: " + msg + ", Data: " + msg.data);
    };

This callback function is reached with a valid token. I create the socket successfully and complete this function as expected. On my local system the onOpened function is then called and I receive the messages from the server. In production onOpened is never called and I never receive any messages. The /_ah/channel/connected/ is also never called.

Is the Channel service not supported with modules? Any thoughts as to what I am missing?

like image 660
David Ward Avatar asked Oct 03 '13 15:10

David Ward


1 Answers

According to Google Enterprise Support (modified slightly from their raw answer):

  1. channel_presence inbound service must be enabled in app.yaml.

    inbound_services:
    - channel_presence
    

    Enabling this inbound service in module’s yaml file (e.g., api.yaml in this question) won’t enable this service.

  2. URL paths starting with */_ah are not dispatchable paths and cannot be routed by dispatch.yaml. Therefore, channel_presence URL paths handlers have to be described in app.yaml.

    handlers:
    - url: /_ah/channel/connected/
      script: mymodule.application
    
like image 62
Emil Sit Avatar answered Oct 08 '22 04:10

Emil Sit