2013-10-03 11 views
10

Utilizzo i moduli App Engine nel mio progetto python. (https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads)Moduli Python App Engine e servizio canale

Sono anche utilizzando canali in m progetto: https://developers.google.com/appengine/docs/python/channel/

voglio indirizzare i messaggi POST/scollegati collegate ('/ _ah/canale/collegato /', '/ _ah/canale/disconnesso/') al mio modulo API. In questo momento non riesco a farli di presentarsi in qualsiasi modulo (predefinito o 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 

Nota: Per essere chiari, tutto funziona in modalità dev localmente.

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) 

Quindi il mio cliente (scritto in JavaScript) post per il mio modulo api e apre un canale.

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

Questa funzione di richiamata viene raggiunta con un token valido. Creo il socket correttamente e completa questa funzione come previsto. Sul mio sistema locale viene quindi chiamata la funzione onOpened e ricevo i messaggi dal server. In produzione onOpened non viene mai chiamato e non ricevo mai messaggi. Anche/_ah/channel/connected/non viene mai chiamato.

Il servizio canale non è supportato con i moduli? Qualche idea su cosa mi manca?

risposta

0

Devi dichiarare un routing Hadler per collegare e disconect URL.

Handler di 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

grazie per la risposta, ma ho paura che non è il problema qui. Non ho inserito il codice qui ma ho aggiunto le route. Non funzionerebbe in modalità dev se non lo avessi fatto. –

+0

Ho aggiunto quel codice per mostrarti cosa intendo. –

6

Secondo Google Enterprise Support (leggermente modificato dalla loro risposta crudo):

  1. channel_presence servizio in entrata deve essere abilitato app.yaml.

    inbound_services: 
    - channel_presence 
    

    L'attivazione di questo servizio in entrata nel file YAML del modulo (ad esempio, api.yaml in questa domanda) non attivare questo servizio.

  2. I percorsi URL che iniziano con */_ah non sono percorsi dispacciabili e non possono essere instradati da dispatch.yaml. Pertanto, i gestori dei percorsi di URL channel_presence devono essere descritti in app.yaml.

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

Quale sarebbe la linea corretta per golang qui: '' script: mymodule.application''? – mattes

+0

mattes- Penso che quella linea sia indipendente dal linguaggio, ma Emil- apprezzerei anche più spiegazioni su come funziona – davidkomer

+0

Per ulteriori informazioni su 'app.yaml', consultare la documentazione specifica della lingua. Per Go, la versione pertinente è https://cloud.google.com/appengine/docs/go/config/appconfig –

0

ho urtato problemi con utilizzando l'API del canale in moduli come bene e ho cercato di lavorare intorno a loro utilizzando un trucco simile a Emil cita reindirizzando le richieste ai moduli.

È stata una configurazione leggermente più complicata, anche perché avevo effettivamente 3 moduli, in cui 2 di loro utilizzavano l'API del canale e uno era il "frontend". Qualcosa di simile a questo:

  • modulo frontend (default)
  • modulo serviceâ (utilizzando il canale api 1)
  • modulo serviceB (utilizzando il canale api 2)

volevo essere in grado di ascoltare alle "notifiche" dai due servizi separati nel frontend.

E il modo in cui sono riuscito a ovviare a questo (in dev) era aggiungere reindirizzamenti al frontend che leggeva i token che avevo prefisso su ciascun servizio e reindirizzamento a ciascun servizio.

"Ottimo, funziona!" Ho pensato, ma quando ho provato a implementare il motore delle app mi sono reso conto che c'era dell'altro in quanto gli endpoint talkgadget utilizzati internamente dall'API del canale sembravano aspettarsi una certa app di origine e quindi non consentivano la comunicazione tra domini.

Così ho finito per utilizzare più progetti invece di moduli e inserendo un "postMessage bridge" iframe HTML per aggirare i problemi del dominio incrociato. E volentieri funziona davvero bene e come effetto collaterale ottengo il doppio dei canali "liberi" da usare.

Ho trovato un problema relativo a questo qui che può essere interessante per voi per rintracciare: https://code.google.com/p/googleappengine/issues/detail?id=10293