Websocket Connect/Disconnect

Hello!

I have a number of nameko services behind a websocket gateway service. The
gateway service maps user_ids to socket_ids and is responsible for routing
messages to and from services and users. What I'm looking to do is get a
disconnect event from the websocket dependency so I can notify services and
clean up the user/socket mapping.

I've added a user dictionary to the websocket_hub, but without a disconnect
event I'm unable to cleanup the mapping. Looking for some pointers on how
to implement this.

Thanks!

    @event_handler("jackpot", "*")
    def jackpot_handler(self, payload):
                 self.handle_event("jackpot", payload)
    
    def handle_event(self, service, payload):
        if "players" in payload:
            players = payload["players"]
            event = payload["event"]
            data = payload["data"]

            if players == "*":
                # Broadcast to any players who have subscribed to service
                self.websocket_hub.broadcast(service, event, data)
            else:
                # Send to specific players
                for player_id in players:
                    socket_id = self.get_player_socket_id(player_id)
                    if socket_id:
                        self.websocket_hub.unicast(socket_id, event, data)

    def get_player_socket_id(self, player_id):
        if hasattr(self.websocket_hub, 'players'):
            if player_id in self.websocket_hub.players:
                socket_id = self.websocket_hub.players[player_id]
                return socket_id

        return None

    def set_player_socket_id(self, player_id, socket_id):
        conn = self.websocket_hub._get_connection(socket_id)
        conn.player_id = player_id

        if not hasattr(self.websocket_hub, 'players'):
            self.websocket_hub.players = dict()

        self.websocket_hub.players[player_id] = socket_id

Hi,

As i mentioned on the ticket
<Issues · nameko/nameko · GitHub, I think you want to
build a new entrypoint, similar to nameko.web.websocket:WebSocketRpc, but
using a modified WebSocketServer that overrides e.g. `add_websocket` to
(also) do something like find your `ConnectedProvider` and fire it

Then you add methods to your service class decorated with your new
entrypoint

Best,
David

···

On Friday, 29 January 2016 16:28:42 UTC, conor.s...@gmail.com wrote:

Hello!

I have a number of nameko services behind a websocket gateway service. The
gateway service maps user_ids to socket_ids and is responsible for routing
messages to and from services and users. What I'm looking to do is get a
disconnect event from the websocket dependency so I can notify services and
clean up the user/socket mapping.

I've added a user dictionary to the websocket_hub, but without a
disconnect event I'm unable to cleanup the mapping. Looking for some
pointers on how to implement this.

Thanks!

    @event_handler("jackpot", "*")
    def jackpot_handler(self, payload):
                 self.handle_event("jackpot", payload)
    
    def handle_event(self, service, payload):
        if "players" in payload:
            players = payload["players"]
            event = payload["event"]
            data = payload["data"]

            if players == "*":
                # Broadcast to any players who have subscribed to service
                self.websocket_hub.broadcast(service, event, data)
            else:
                # Send to specific players
                for player_id in players:
                    socket_id = self.get_player_socket_id(player_id)
                    if socket_id:
                        self.websocket_hub.unicast(socket_id, event, data)

    def get_player_socket_id(self, player_id):
        if hasattr(self.websocket_hub, 'players'):
            if player_id in self.websocket_hub.players:
                socket_id = self.websocket_hub.players[player_id]
                return socket_id

        return None

    def set_player_socket_id(self, player_id, socket_id):
        conn = self.websocket_hub._get_connection(socket_id)
        conn.player_id = player_id

        if not hasattr(self.websocket_hub, 'players'):
            self.websocket_hub.players = dict()

        self.websocket_hub.players[player_id] = socket_id

Thanks, I'll give that a shot.

···

On Friday, January 29, 2016 at 2:01:44 PM UTC-5, David Szotten wrote:

Hi,

As i mentioned on the ticket
<Issues · nameko/nameko · GitHub, I think you want to
build a new entrypoint, similar to nameko.web.websocket:WebSocketRpc, but
using a modified WebSocketServer that overrides e.g. `add_websocket` to
(also) do something like find your `ConnectedProvider` and fire it

Then you add methods to your service class decorated with your new
entrypoint

Best,
David

On Friday, 29 January 2016 16:28:42 UTC, conor.s...@gmail.com wrote:

Hello!

I have a number of nameko services behind a websocket gateway service.
The gateway service maps user_ids to socket_ids and is responsible for
routing messages to and from services and users. What I'm looking to do is
get a disconnect event from the websocket dependency so I can notify
services and clean up the user/socket mapping.

I've added a user dictionary to the websocket_hub, but without a
disconnect event I'm unable to cleanup the mapping. Looking for some
pointers on how to implement this.

Thanks!

    @event_handler("jackpot", "*")
    def jackpot_handler(self, payload):
                 self.handle_event("jackpot", payload)
    
    def handle_event(self, service, payload):
        if "players" in payload:
            players = payload["players"]
            event = payload["event"]
            data = payload["data"]

            if players == "*":
                # Broadcast to any players who have subscribed to service
                self.websocket_hub.broadcast(service, event, data)
            else:
                # Send to specific players
                for player_id in players:
                    socket_id = self.get_player_socket_id(player_id)
                    if socket_id:
                        self.websocket_hub.unicast(socket_id, event, data)

    def get_player_socket_id(self, player_id):
        if hasattr(self.websocket_hub, 'players'):
            if player_id in self.websocket_hub.players:
                socket_id = self.websocket_hub.players[player_id]
                return socket_id

        return None

    def set_player_socket_id(self, player_id, socket_id):
        conn = self.websocket_hub._get_connection(socket_id)
        conn.player_id = player_id

        if not hasattr(self.websocket_hub, 'players'):
            self.websocket_hub.players = dict()

        self.websocket_hub.players[player_id] = socket_id

Cool. Let me know how you get on and if you need any more help/advice.

D

···

On Friday, 29 January 2016 19:34:30 UTC, conor.s...@gmail.com wrote:

Thanks, I'll give that a shot.

On Friday, January 29, 2016 at 2:01:44 PM UTC-5, David Szotten wrote:

Hi,

As i mentioned on the ticket
<Issues · nameko/nameko · GitHub, I think you want to
build a new entrypoint, similar to nameko.web.websocket:WebSocketRpc, but
using a modified WebSocketServer that overrides e.g. `add_websocket` to
(also) do something like find your `ConnectedProvider` and fire it

Then you add methods to your service class decorated with your new
entrypoint

Best,
David

On Friday, 29 January 2016 16:28:42 UTC, conor.s...@gmail.com wrote:

Hello!

I have a number of nameko services behind a websocket gateway service.
The gateway service maps user_ids to socket_ids and is responsible for
routing messages to and from services and users. What I'm looking to do is
get a disconnect event from the websocket dependency so I can notify
services and clean up the user/socket mapping.

I've added a user dictionary to the websocket_hub, but without a
disconnect event I'm unable to cleanup the mapping. Looking for some
pointers on how to implement this.

Thanks!

    @event_handler("jackpot", "*")
    def jackpot_handler(self, payload):
                 self.handle_event("jackpot", payload)
    
    def handle_event(self, service, payload):
        if "players" in payload:
            players = payload["players"]
            event = payload["event"]
            data = payload["data"]

            if players == "*":
                # Broadcast to any players who have subscribed to service
                self.websocket_hub.broadcast(service, event, data)
            else:
                # Send to specific players
                for player_id in players:
                    socket_id = self.get_player_socket_id(player_id)
                    if socket_id:
                        self.websocket_hub.unicast(socket_id, event,
data)

    def get_player_socket_id(self, player_id):
        if hasattr(self.websocket_hub, 'players'):
            if player_id in self.websocket_hub.players:
                socket_id = self.websocket_hub.players[player_id]
                return socket_id

        return None

    def set_player_socket_id(self, player_id, socket_id):
        conn = self.websocket_hub._get_connection(socket_id)
        conn.player_id = player_id

        if not hasattr(self.websocket_hub, 'players'):
            self.websocket_hub.players = dict()

        self.websocket_hub.players[player_id] = socket_id

Hi David,

I played around with creating a new entry point but in the end opted to
extend the WebSocketHub. I actually just tied into the "cleanup_websocket"
function to remove the user from the mapping.

Appreciate the help and am really liking the framework.. our monolith's
days are numbered :).

Thanks,
Conor

···

On Monday, February 1, 2016 at 4:11:16 AM UTC-5, David Szotten wrote:

Cool. Let me know how you get on and if you need any more help/advice.

D

On Friday, 29 January 2016 19:34:30 UTC, conor.s...@gmail.com wrote:

Thanks, I'll give that a shot.

On Friday, January 29, 2016 at 2:01:44 PM UTC-5, David Szotten wrote:

Hi,

As i mentioned on the ticket
<Issues · nameko/nameko · GitHub, I think you want to
build a new entrypoint, similar to nameko.web.websocket:WebSocketRpc, but
using a modified WebSocketServer that overrides e.g. `add_websocket` to
(also) do something like find your `ConnectedProvider` and fire it

Then you add methods to your service class decorated with your new
entrypoint

Best,
David

On Friday, 29 January 2016 16:28:42 UTC, conor.s...@gmail.com wrote:

Hello!

I have a number of nameko services behind a websocket gateway service.
The gateway service maps user_ids to socket_ids and is responsible for
routing messages to and from services and users. What I'm looking to do is
get a disconnect event from the websocket dependency so I can notify
services and clean up the user/socket mapping.

I've added a user dictionary to the websocket_hub, but without a
disconnect event I'm unable to cleanup the mapping. Looking for some
pointers on how to implement this.

Thanks!

    @event_handler("jackpot", "*")
    def jackpot_handler(self, payload):
                 self.handle_event("jackpot", payload)
    
    def handle_event(self, service, payload):
        if "players" in payload:
            players = payload["players"]
            event = payload["event"]
            data = payload["data"]

            if players == "*":
                # Broadcast to any players who have subscribed to
service
                self.websocket_hub.broadcast(service, event, data)
            else:
                # Send to specific players
                for player_id in players:
                    socket_id = self.get_player_socket_id(player_id)
                    if socket_id:
                        self.websocket_hub.unicast(socket_id, event,
data)

    def get_player_socket_id(self, player_id):
        if hasattr(self.websocket_hub, 'players'):
            if player_id in self.websocket_hub.players:
                socket_id = self.websocket_hub.players[player_id]
                return socket_id

        return None

    def set_player_socket_id(self, player_id, socket_id):
        conn = self.websocket_hub._get_connection(socket_id)
        conn.player_id = player_id

        if not hasattr(self.websocket_hub, 'players'):
            self.websocket_hub.players = dict()

        self.websocket_hub.players[player_id] = socket_id

Seems great to use websockets, I haven't found a working sample nor documentation. Anyone have a pointer for me or preferably an example of how to host a websocket server and use it in nameko? Thanks!

Here is a simple example that makes a request to another service.

from nameko.web.websocket import rpc

from nameko.rpc import RpcProxy

class GatewayService(object):
    name = "gateway"

    other_service = RpcProxy("other_service")

    @rpc
    def service_request(self, socket_id, service, method, args):
        return getattr(getattr(self, service), method)(**args)

Then connect to ws://localhost:8080/ws, using whichever port you configured
in your config.

From the client, we send a packet that looks like this

    data = {
        "method": "service_request",
        "data": {
            "service": "other_service",
            "method": "other_service_method",
            "args": {"some_arg": "value", "some_arg_2": "value"}
        }
    }

The idea being that the websocket gateway is just a relay to other services.

···

On Friday, March 4, 2016 at 5:32:04 PM UTC-5, remco....@gmail.com wrote:

Seems great to use websockets, I haven't found a working sample nor
documentation. Anyone have a pointer for me or preferably an example of how
to host a websocket server and use it in nameko? Thanks!