1
votes

I am building an app for GAE using python API. It is running here. It is a multi-player game. I use the Channel API to communicate game state between players.

But in the app engine the onmessage handler of the channel is not called. The onopen handler is called. onerror or onclose are not called as well. Weird thing is this works perfectly in the local development server.

Is it possible that something like this can work on the development server but not in the app engine itself?

I'll be really really glad if someone can look into following description of my app and help me to figure out what has happened. Thank you.

I looked into this and this questions, but I haven't done those mistakes.

<script>

        sendMessage = function(path, opt_param, opt_param2) {

            path += '?g=' + state.game_key;
            if (opt_param) {
                path += '&' + opt_param;
            }
            if (opt_param2) {
                path += '&' + opt_param2;
            }
            var xhr = new XMLHttpRequest();
            xhr.open('POST', path, true);
            xhr.send();
        };

Above function is used to make a post request to the server.

onOpened = function() {
        sendMessage('/resp');
        console.log('channel opened');
    };

Above is the function I want to be called when the channel is open for the first time. I send a post to the '/resp' address.

onMessage = function(m) {
    console.log('message received');
    message = JSON.parse(m.data);
    //do stuff with message here 
};

I want to process the response I get from that request in the above function.

following are onerror and onclose handlers.

onError = function() {
        console.log('error occured');
        channel = new goog.appengine.Channel('{{ token }}');
        socket = channel.open();
    };

    onClose = function() {
        console.log('channel closed');
    };

    channel = new goog.appengine.Channel('{{ token }}');
    socket = channel.open();
    socket.onopen = onOpened;
    socket.onmessage = onMessage;
    socket.onclose = onClose;
    socket.onerror = onError;

</script>

This script is at the top of body tag. This works fine in my local development server. But on the app engine,
onOpen function is called.
I can see the request to /resp in the sever logs.
but onMessage is never called. The log 'message received' is not present in the console.

this is the server side.

token = channel.create_channel(user.user_id() + game.user1.user_id() )
url = users.create_logout_url(self.request.uri)
template_values = {
                  'token' : token,
                  'id' : pid,
                  'game_key' : str(game.user1.user_id()),
                  'url': url
                 }
path = os.path.join(os.path.dirname(__file__), 'game.html')
self.response.out.write(template.render(path, template_values)) 

and this is in the request handler for '/resp' request. My application is a multi-player card game. And I want to inform other players that a new player is connected. Even the newly connected player will also get this message.

class Responder(webapp2.RequestHandler):            
    def post(self):
        user = users.get_current_user()
        game = OmiGame.get_by_key_name(self.request.get('g'))
        if game.user1:
            channel.send_message(game.user1.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname()))
        if game.user2:
            channel.send_message(game.user2.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname())) 

EDIT : user1 is the user who created the game. I want tokens of other players' to be created by adding the user1's user_id and the relevant users user_id. Could something go wrong here?

So when I try this on the local dev server I get these messages perfectly fine. But on the GAE onMessage is not called. This is my app. When the create button is clicked page with above script is loaded and "playernickname connected" should be displayed.

1

1 Answers

3
votes

The channel behavior on the dev server and production are somewhat different. On the dev server, the channel client just polls http requests frequently. On production, comet style long polling is used.

I suspect there may be a problem with making the XHR call inside the onOpened handler. In Chrome at least, I see that the next talkgadget GET request used by the channel API is cancelled.

Try calling sendMessage('/resp') outside of the onMessage function. Perhaps enqueue it to get run by using setTimeout so it's called later after you return.