Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for resuming sessions #66

Closed
wants to merge 9 commits into from

Conversation

WizzyGeek
Copy link
Contributor

@WizzyGeek WizzyGeek commented Aug 13, 2020

This is #59 but i kind of squashed all the commits.

Added New attributes

  • Websocket.resume_session: bool
  • Websocket.resume_timeout: float
  • Websocket.resume_key: Union[str, wavelink.websocket._Key, object] (Best left None)
  • Websocket.payload_timeout: float This is basically how recent requests shall be sent to the server
  • Websocket.reset() method.
  • Websocket.close() method.
  • Node.heartbeat: float
  • wavelink.errors.NodeSessionClosedError: This error is handled within wavelink, but a warning message is logged for now
  • Other private attributes:
    • Websocket._send_queue method: called on connect if session is resumed
    • Websocket._can_resume: wether resuming is enabled and configured.
    • Websocket._queue: Present only is Websocket.resume_session is True
    • wavelink.websocket._TimedQueue: An asyncio.Queue subclass, which stores data only for a certain amount of time
    • wavelink.websocket._Key: The default key, this generates secure passwords, any other classes must be similar in functionality
    • Node Attributes: pass the arguments to Node.connect method.
      • Node._resume_session
      • Node._resume_timeout
      • Node._payload_timeout
      • Node._resume_key

Example

  • Basic

async def start_nodes(self) -> None:
    """Connect and intiate nodes."""
    nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                      'port': 80,
                      'rest_uri': 'http://lavaserver.badhost.com',
                      'password': "verytrivialpassword",
                      'identifier': 'MAIN',
                      'region': 'us_central',
                      'resume_session': True # rest is default
                      }}

    for n in nodes.values():
        await self.bot.wavelink.initiate_node(**n)
  • Complete

Key.py

from somewhere import SomeSecurePasswordGenerator

class key:
    def __init__(self, len):
        self.len = len
        self.persistent = None
        self.__repr__()

    def __str__(self):
        return self.persistent

    def __repr__(self):
        """This should generate a key and shall make it persistent """
        self.persistent = SomeSecurePasswordGenerator(self.len)
        return self.persistent

music_cog.py

from Key import key 
...

class my_cog(commands.Cog):
     ...

     async def start_nodes(self) -> None:
        """Connect and intiate nodes."""
        nodes = {'MAIN': {'host': 'lavaserver.badhost.com',
                          'port': 80,
                          'rest_uri': 'http://lavaserver.badhost.com',
                          'password': "verytrivialpassword",
                          'identifier': 'MAIN',
                          'region': 'us_central',
                          'heartbeat': 40.0, # ping the server every 40s
                          'resume_session': True,
                          'resume_timeout': 90.0,
                          'resume_key': key(10) # or "Astring".
                          'payload_timeout': 40.0
                          }}

        for n in nodes.values():
            await self.bot.wavelink.initiate_node(**n)
    
    ...

New features proposed in this PR

Resuming

When the bot disconnects from the node (eg: 1006) then the lavalink server keeps on playing the music until session timeout, this allows the bot to reconnect and take control of the session. This PR implements this lavalink feature.

Key protocol

The key must be an object instance or a str. The __repr__ method should return a new key. The __str__method must return the last key that was generated by __repr__. This protocol only defines these two methods since it needs to maintain compatibilty with str.

Queueing

After the Node disconnects, we try to reconnect multiple times with a capped backoff before timeout. during this time the requests to the node are queued in an asyncio.Queue subclass whose payload expires after some time.
This could be useful when you have an high timeout but want to only send recent requests.

Semver

This is a minor change. The changes are not breaking, assuming no-one initializes Node instances directly.

WizzyGeek and others added 2 commits August 13, 2020 12:34
deleted unnecessary attributes in connect
@EvieePy
Copy link
Member

EvieePy commented Jun 22, 2021

Closing this as Branch 1.0 now supersedes master. I would like it if you could implement resumes on 1.0 so feel free to do so. If not I will keep it in the todo list. Thanks for the PR.

@EvieePy EvieePy closed this Jun 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants