crossbario / crossbario/autobahn-python

Until when component.stop is supposed to block ?

Open
#1,173 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs-investigation wamp
Dominant language
Python
Stars
2.5k
Forks
768
PR merge metrics
No merged PRs in 30d

Description

After one call stop on a component this will return once the session (if any) has left the realm, but not until it got fully disconnected from the WAMP router.

    comp = Component(transports=conf["transports"], realm=conf["realm"])

    comp_ready = asyncio.Event()
    comp_disconnected = asyncio.Event()

    @comp.on_ready
    async def on_ready(*args, **kwargs):
        print("ready")
        comp_ready.set()

    @comp.on_leave
    async def on_leave(*args, **kwargs):
        print("leaving")

    @comp.on_disconnect
    async def on_disconnect(*args, **kwargs):
        print("disconnecting")
        comp_disconnected.set()

    async def stop():
        await comp_ready.wait()
        print("stopping")
        await comp.stop()  # or just comp.stop(), same result
        print("stopped")
        await comp_disconnected.wait()

    async def start_and_stop(loop):
        # start the component, stop it when it's ready, 
        # wait for the session to be disconnected.
        await asyncio.gather(
            asyncio.ensure_future(comp.start(loop), loop=loop), 
            stop()
        )

    txaio.use_asyncio()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(start_and_stop(loop))

Output expected:

ready
stopping
leaving
disconnecting
stopped

but got:

ready
stopping
leaving
stopped
disconnecting

Looking at the code it might be by design (I'm a little bit lost within all the callbacks, does session.leave return after on_leave handlers has been resolved or does it wait for the on_disconnect handlers as well ?):
https://github.com/crossbario/autobahn-python/blob/278fb3880bb9209c8c76baa3d2cba9725f7ce446/autobahn/wamp/component.py#L702-L716

Anyway it make it hard to properly stop the asyncio loop only once every component completed all their scheduled task as their is no easy way to wait for them,
as stated here "Event loop stopped before Future completed" :
https://github.com/crossbario/autobahn-python/blob/278fb3880bb9209c8c76baa3d2cba9725f7ce446/autobahn/asyncio/component.py#L388-L394

ie: No easy way to stop the loop once every components are done because in the current state there are still pending on_disconnect tasks when components are considered done.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the ordering in autobahn/wamp/component.py around lines 702-716 using the asyncio component example in the issue. Then inspect autobahn/asyncio/component.py around lines 388-394 and the session leave, on_leave, and on_disconnect flow. Done means the stop semantics are clarified and covered by a regression test, or the documented behavior explains how callers should wait for full disconnection.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.