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

Handling exceptions in the API: The cause of the issue and a bad kludge workaround #86

Open
00prometheus opened this issue Apr 11, 2023 · 1 comment

Comments

@00prometheus
Copy link

00prometheus commented Apr 11, 2023

Right now, the Task returned by asyncio.ensure_future() in avanza_socket.init() is not stored or handled by the API. A reference to the Task must be maintained for as long as the Task is active, or else the Task gets garbage collected at some random time. You also need the reference to be able to either await or asyncio.gather() the Task so you can catch any exception from the connection (e.g. ConnectionClosedError).

You further need to regularly access Avanza within the account's timeout period to keep the login alive (you can select the timeout in your account's settings on Avanza).

Since the Task is not returned from the API right now, I have implemented a bad kludge as a temporary workaround. I use asyncio.all_tasks() to get all Tasks in the process and dig into the Task's internals (works in Python 3.11) to guess which one is the right one. I have a separate loop where I call avanza.get_position() and an asyncio.sleep() to do the keep-alive. So this is my code right now:

task_list = asyncio.all_tasks()
avanza_coro=None
for coro in task_list:
    if coro.get_stack()[0].f_code.co_name == "__create_socket":
        avanza_coro=coro                                                                               
        break
keep_alive_future = asyncio.create_task(keep_alive(avanza))
task_results=await asyncio.gather(avanza_coro, keep_alive_future)

I have a try-catch around the whole thing and recreate the Avanza connection whenever I get an exception.

It would be good if the API would give us the Task properly so I could make that code a bit nicer.

@Qluxzz
Copy link
Owner

Qluxzz commented May 1, 2024

What code changes would be needed for this to work?
Is just returning the task from ensure_future enough for it to work, or do you see a better way to structure it?

async def init(self):
    task = asyncio.ensure_future(self.__create_socket())
    await self.__wait_for_websocket_to_be_connected()
    return task

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

No branches or pull requests

2 participants