Skip to content

Start a bluesky event loop at the start of a test session#1492

Merged
DominicOram merged 6 commits intomainfrom
fix_leftover_asyncio_tasks
Sep 3, 2025
Merged

Start a bluesky event loop at the start of a test session#1492
DominicOram merged 6 commits intomainfrom
fix_leftover_asyncio_tasks

Conversation

@DominicOram
Copy link
Contributor

@DominicOram DominicOram commented Aug 29, 2025

Fixes #1204

Repeated recreating of the RE was also causing issues with too many file handles open when running the tests locally. Not sure of the underlying cause for that but this seems like a reasonable thing to do anyway. It also seems to shave a couple of seconds off the tests too.

Additionally:

  • Stops some tests from leaving leftover asyncio tasks
  • Fixes test_attach_data_session_metadata_wrapper_with_no_provider_is_noop, which didn't assert anything was broken in isolation

Instructions to reviewer on how to test:

  1. Confirm tests still pass

Checks for reviewer

  • Would the PR title make sense to a scientist on a set of release notes
  • If a new device has been added does it follow the standards
  • If changing the API for a pre-existing device, ensure that any beamlines using this device have updated their Bluesky plans accordingly
  • Have the connection tests for the relevant beamline(s) been run via dodal connect ${BEAMLINE}

@codecov
Copy link

codecov bot commented Aug 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.75%. Comparing base (72db5ad) to head (b3d5e2c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1492   +/-   ##
=======================================
  Coverage   98.75%   98.75%           
=======================================
  Files         235      235           
  Lines        8642     8645    +3     
=======================================
+ Hits         8534     8537    +3     
  Misses        108      108           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@DominicOram DominicOram changed the title Fix too many file handles Start a bluesky event loop at the start of a test session Aug 31, 2025
@DominicOram DominicOram marked this pull request as ready for review August 31, 2025 11:47
@DominicOram DominicOram requested a review from a team as a code owner August 31, 2025 11:47
Copy link
Contributor

@olliesilvester olliesilvester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks. I haven't thoroughly checked to see if every RE was removed from the tests, but it looks like you got most of them

@pytest.fixture
async def RE():
@pytest.fixture(scope="session", autouse=True)
async def _ensure_running_bluesky_event_loop():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it's doable with the current tests, but I think the relationship between these fixtures should be reversed:

@pytest.fixture(scope="session", autouse=True)
async def _loop() -> AbstractEventLoop:
    return new_event_loop()

@pytest.fixture()
def RE(_loop: AbstractEventLoop):
    yield RunEngine(loop=_loop)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to check out locally and see if the tests pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From playing with it locally, it looks like

@pytest.fixture(scope="session", autouse=True)
async def _loop() -> AsyncGenerator[AbstractEventLoop]:
    loop = new_event_loop()
    yield loop
    loop.stop()

@pytest.fixture(scope="session", autouse=True)
def RE(_loop: AbstractEventLoop):
    yield RunEngine(loop=_loop, call_returns_result=True)

Is the correct setup, and lets us remove the places where additional RunEngines are created in test_oav_utils.py

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I agree it would be good to get the relationship between them so that the RE uses the same event loop. However, having the RE as @pytest.fixture(scope="session", autouse=True) seems wrong to me because now you have one RE for all tests and, unlike the event loop, the RE quite regularly holds state. For example, if one test adds a callback and forgets to remove it you're now using it in subsequent ones.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's annoying that set_bluesky_loop is internal to bluesky, so just creating the loop and later creating the RunEngine with the same loop isn't sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, we're going to merge this as is and follow up with #1501 if required

@DominicOram DominicOram merged commit f3b53e9 into main Sep 3, 2025
11 checks passed
@DominicOram DominicOram deleted the fix_leftover_asyncio_tasks branch September 3, 2025 08:54
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.

Create session fixture for starting bluesky event loop

3 participants