2013-10-03 7 views
10

Ich verwende App Engine-Module in meinem Python-Projekt. (https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads)App Engine Python-Module und Channel-Service

Ich bin auch Kanäle in m-Projekt mit: https://developers.google.com/appengine/docs/python/channel/

Ich möchte die Verbunden/Unterbrochen Post-Nachrichten lenken ('/ _ah/Kanal/verknüpften /', ‚/ _ah/Kanal/getrennt/') zu meinem API-Modul. Im Moment kann ich nicht bekommen sie in jedem Modul (Standard oder 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

zeigen
application: integrate 

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

Hinweis: Nur um klar zu sein, das alles funktioniert im Dev-Modus lokal.

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 mein Client (geschrieben in JavaScript) Beiträge zu meinem API-Modul und öffnet einen Kanal.

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); 
    }; 

Diese Callback-Funktion wird mit einem gültigen Token erreicht. Ich erstelle das Socket erfolgreich und vervollständige diese Funktion wie erwartet. Auf meinem lokalen System wird dann die onOpened-Funktion aufgerufen und ich erhalte die Nachrichten vom Server. In der Produktion onOpened wird nie aufgerufen und ich bekomme nie irgendwelche Nachrichten. Das/_ah/channel/connected/wird auch nie aufgerufen.

Wird der Channel-Dienst nicht mit Modulen unterstützt? Irgendwelche Gedanken, was ich vermisse?

Antwort

0

Sie müssen ein HADLER-Routing für die Verbindung deklarieren und URLs ablehnen.

Handler-Routing in main.py:

application = webapp2.WSGIApplication([ 
    ... 
    # Define a URL routing for /_ah/channel/connected/ 
    webapp2.Route(r'/_ah/channel/connected/', 
        handler=ChannelConnectedHandler, 
        name='channel_connected') 

], debug=True, config=webapp2_config) 


# Implement class handler of /_ah/channel/connected/ 
class ChannelConnectedHandler(webapp2.RequestHandler): 
    def post(self): 
     client_id = self.request.get('from') 
     logging.info('client %s has connected!' % client_id) 
     ... 
+1

Danke, aber ich habe Angst, dass hier nicht das Problem ist. Ich habe den Code hier nicht gepostet, aber ich habe die Routen hinzugefügt. Es würde nicht im Dev-Modus funktionieren, wenn ich nicht hätte. –

+0

Ich habe diesen Code hinzugefügt, um Ihnen zu zeigen, was ich meine. –

6

Laut Google Enterprise Support (leicht modifiziert von ihrer rohen Antwort):

  1. channel_presence Inbound-Service muss in app.yaml aktiviert werden.

    inbound_services: 
    - channel_presence 
    

    Aktivierung diesen Inbound-Service in YAML-Datei des Moduls (zum Beispiel api.yaml in dieser Frage) wird diesen Dienst nicht aktivieren.

  2. URL-Pfade, die mit */_ah beginnen, sind keine ausrichtbaren Pfade und können nicht von dispatch.yaml geroutet werden. Daher müssen channel_presence URL-Pfade-Handler in app.yaml beschrieben werden.

    handlers: 
    - url: /_ah/channel/connected/ 
        script: mymodule.application 
    
+0

Was wäre die richtige Zeile für Golang hier: '' Skript: mymodule.application''? – mattes

+0

mattes- Ich denke, diese Zeile ist sprachunabhängig, aber Emil - ich würde auch mehr Erklärung dafür, wie das funktioniert, schätzen – davidkomer

+0

Weitere Informationen über 'app.yaml' finden Sie in der sprachspezifischen Dokumentation. Für Go finden Sie die entsprechende Version unter https://cloud.google.com/appengine/docs/go/config/appconfig –

0

Ich habe auch in den Modulen unter Verwendung des Channel-API in Probleme gestoßen und ich versuchte, um sie herum zu arbeiten, um einen ähnlichen Trick wie Emil erwähnt durch die Anforderungen an die Module umgeleitet wird.

Es war ein etwas komplizierteres Setup, obwohl ich eigentlich 3 Module hatte, von denen 2 die Channel API nutzten und eines das 'Frontend' war. Etwas wie folgt aus:

  • Modul Frontend (default)
  • Modul serviceA
  • Modul serviceB (Kanal api 1 verwendet wird) (mit Kanal api 2)

Ich wollte in der Lage sein zu hören auf "Benachrichtigungen" von den zwei separaten Diensten im Frontend.

Und die Art und Weise, wie ich das geschafft habe (im Entwickler), war das Hinzufügen von Redirects zum Frontend, die die Tokens lesen, die ich bei jedem Service vorangestellt hatte und die zu jedem Dienst umgeleitet wurden.

"Großartig, es funktioniert!" Ich dachte, aber dann, als ich versuchte, in der App-Engine zu implementieren, erkannte ich, dass da mehr dran ist, da die von der Channel-API intern verwendeten talkgadget-Endpunkte eine bestimmte Quell-App zu erwarten schienen und somit keine domänenübergreifende Kommunikation zuließen.

So endete ich mit mehreren Projekten anstelle von Modulen und indem ich eine HTML-Iframe "PostMessage-Brücke", um die Cross-Domain-Probleme zu umgehen. Und gerne klappt es wirklich gut und als Nebeneffekt bekomme ich doppelt so viele "freie" Kanäle zu nutzen.

fand ich ein Problem dazu hier im Zusammenhang, die für interessant sein kann, die Sie verfolgen: https://code.google.com/p/googleappengine/issues/detail?id=10293 für die Beantwortung