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

Fix blocking I/O in the event loop when loading timezones #117721

Merged
merged 25 commits into from
May 20, 2024
Merged

Fix blocking I/O in the event loop when loading timezones #117721

merged 25 commits into from
May 20, 2024

Conversation

bdraco
Copy link
Member

@bdraco bdraco commented May 19, 2024

Breaking change

Constructing ZoneInfo objects may do blocking I/O to load the zone info from disk if the timezone passed is not in the cache.

dt_util.async_get_time_zone is now available to replace dt_util.get_time_zone to fetch a time zone in the event loop which is async safe and will not do blocking I/O in the event loop.

hass.config.set_time_zone is deprecated and replaced with hass.config.async_set_time_zone. hass.config.set_time_zone will be removed in 2025.6. Setting the time zone only affects tests, as no integration should be calling this function in production.

Examining dt_util.DEFAULT_TIME_ZONE directly is deprecated and dt_util.get_default_time_zone() should be used instead.

If your integration needs to construct ZoneInfo objects in the event loop, it is recommended to use the aiozoneinfo library.

Proposed change

aiozoneinfo is a simple wrapper that check if the ZoneInfo is in the cache, and if not it will load it in the executor since ZoneInfo will do blocking I/O in the loop if the zone info is not in the cache https://github.com/python/cpython/blob/a3db4e8f964499eabeddb19a6201f3d3b73d7443/Lib/zoneinfo/_zoneinfo.py#L73. A new library was created because integrations have the same problem and will likely want to use it in their PyPI package.

We have this problem in a few different places in the code. To avoid solving it multiple different ways, dt_util.async_get_time_zone is now available.

Everything that used dt_util.DEFAULT_TIME_ZONE, manually constructed the zone info, or used dt_util.get_time_zone(entity.hass.config.time_zone) has been updated to dt_util.get_default_time_zone()

All instances in core that did blocking I/O to load the time zone data from disk have been fixed except for airnow which needs a more involved solution, see #117615

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
  • Untested files have been added to .coveragerc.

To help with the load of incoming pull requests:

@home-assistant home-assistant bot added cla-signed core small-pr PRs with less than 30 lines. labels May 19, 2024
@bdraco bdraco changed the title Fix blocking I/O in the event loop to load timezones with aiozoneinfo Add method to avoid blocking I/O in the event loop to when loading timezones May 19, 2024
@bdraco
Copy link
Member Author

bdraco commented May 19, 2024

draft because all the current usage needs to be analyzed to see what its going to take to move to the new method as some of these calls are not in coros

@MartinHjelmare MartinHjelmare changed the title Add method to avoid blocking I/O in the event loop to when loading timezones Add method to avoid blocking I/O in the event loop when loading timezones May 19, 2024
@bdraco bdraco added the deprecation Indicates a breaking change to happen in the future label May 20, 2024
@bdraco bdraco changed the title Add method to avoid blocking I/O in the event loop when loading timezones Fix blocking I/O in the event loop when loading timezones May 20, 2024
@farmio farmio mentioned this pull request May 20, 2024
20 tasks
Copy link
Member

@frenck frenck left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @bdraco 👍

../Frenck

@frenck frenck merged commit 5a609c3 into dev May 20, 2024
34 checks passed
@frenck frenck deleted the zoneinfo branch May 20, 2024 09:06
@bdraco
Copy link
Member Author

bdraco commented May 20, 2024

thanks

bajansen pushed a commit to bajansen/homeassistant that referenced this pull request May 20, 2024
@github-actions github-actions bot locked and limited conversation to collaborators May 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
blocking event loop cla-signed core deprecation Indicates a breaking change to happen in the future small-pr PRs with less than 30 lines.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants