Skip to content

Add support for simultaneous runs of Script helper - Part 2#32442

Merged
balloob merged 15 commits intohome-assistant:devfrom
pnbruckner:script-modes
Mar 11, 2020
Merged

Add support for simultaneous runs of Script helper - Part 2#32442
balloob merged 15 commits intohome-assistant:devfrom
pnbruckner:script-modes

Conversation

@pnbruckner
Copy link
Copy Markdown
Contributor

@pnbruckner pnbruckner commented Mar 3, 2020

Proposed change

This is a follow-on to #31937.

While working to use those changes in the script integration a few bugs were discovered. Also it became clear that a slight change of direction was needed regarding how to configure/handle long running scripts. Lastly a new queue mode was added which can be very helpful in certain scenarios (especially for automation action sequences.)

The changes were broken up into several, smaller commits to help make the review process easier.

New Script helper option

Replaces if_running.

script_mode

  • Controls what happens if Script run (i.e., async_run called) while previous run has not yet completed.
  • Values:
    • error Raise an exception
    • ignore Return without doing anything (previous run continues as-is)
    • legacy Implements previous behavior, which is to return when done, or when suspended by delay or wait_template, whichever comes first. This is the default
    • parallel Start run in new task
    • queue Start new run when previous runs have completed
    • restart Stop previous run before starting new run

New script.turn_on service parameter

Replaces run_mode.

Background/blocking behavior is now controlled by the script.turn_on service. The default (which also applies when calling a script "directly" -- script.abc -- or via the script.toggle service) is to be fully blocking. To run a script in the "background" a new blocking parameter to the script.turn_on service has been defined:

- service: script.turn_on
  entity_id: script.abc
  data:
    blocking: false
    variables: ...

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)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

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
  • The code has been formatted using Black (black --fast 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.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

Comment thread homeassistant/helpers/script.py
Comment thread homeassistant/helpers/script.py Outdated
Comment thread homeassistant/helpers/script.py Outdated
Comment thread homeassistant/helpers/script.py
Comment thread homeassistant/helpers/script.py Outdated
Comment thread homeassistant/helpers/script.py
Comment thread homeassistant/helpers/script.py Outdated
Comment thread homeassistant/helpers/script.py Outdated
@pnbruckner
Copy link
Copy Markdown
Contributor Author

I've made the other changes already requested and tested them. I'll go ahead and make another commit so they can be looked over while we decide what to do about stopping/restarting invoked scripts.

Comment thread homeassistant/core.py
Call change listener immediately if its a callback
- Remove background/blocking _ScriptRun subclasses which are no longer needed.
This makes restart mode behavior consistent with parallel & queue modes.
- Call all script services (except script.turn_off) with no time limit.
- Fix handling of lock in _QueuedScriptRun and add comments to make it
  clearer how this code works.
- Move cancel shielding "up" from _ScriptRun.async_run to Script.async_run
  (and apply to new style scripts only.) This makes sure Script class also
  properly handles cancellation which it wasn't doing before.
- In _ScriptRun._async_call_service_step, instead of using script.turn_off
  service, just cancel service call and let it handle the cancellation
  accordingly.
@pnbruckner
Copy link
Copy Markdown
Contributor Author

pnbruckner commented Mar 6, 2020

FYI, I did a rebase that I need to force push to resolve the conflicts from your PR.

@balloob
Copy link
Copy Markdown
Member

balloob commented Mar 6, 2020

This looks good ! We can merge this after conflicts resolved. Conflicts caused by me moving some constants to config_validation.py.

Let's do the unshielding of the service call in core.py in a future PR.

@pnbruckner
Copy link
Copy Markdown
Contributor Author

pnbruckner commented Mar 7, 2020

I did some ad hoc testing and found a bug in the turn off sequence initiated by a cancellation. (Turning off was originally done via a service so I had overlooked this one.)

I want to commit that fix, then do a lot more testing (both with additional formal tests as well as ad hoc) before we merge this change. Give me at least a few more days.

Regarding removing the shield from services.async_call, I suppose it makes sense to do that separately since it has a potential for a large impact. I've been testing with that change and found at least a couple tests from other components that seem to be affected by the small timing change (i.e., probably one less await inside the call.) see recent comment in conversation about changes to homeassistant/core.py above.

- Add missing call to change listener in Script.async_run
  in cancelled path.
- Cancel service task if ServiceRegistry.async_call cancelled.
@pnbruckner
Copy link
Copy Markdown
Contributor Author

Force push required due to rebase. See last commit for changes since last review.

@pnbruckner pnbruckner requested a review from balloob March 9, 2020 14:28
@pnbruckner
Copy link
Copy Markdown
Contributor Author

I'd still like to do more testing, possibly adding more formal tests, before this PR is merged.

Comment thread homeassistant/core.py Outdated
- Don't log asyncio.CancelledError exceptions.
- Make change_listener a public attribute.
- Test overhaul
  - Parametrize tests.
  - Use common test functions.
  - Mock timeout so tests don't need to wait for real time to elapse.
  - Add common function for waiting for script action step.
@pnbruckner
Copy link
Copy Markdown
Contributor Author

Assuming the tests pass (they did locally), and you don't find any other issues, then I think we can put this one to bed and I'll start working on the ServiceRegistry.async_call changes we discussed.

@balloob balloob merged commit 5f5cb8b into home-assistant:dev Mar 11, 2020
@balloob
Copy link
Copy Markdown
Member

balloob commented Mar 11, 2020

Booooooooooom 🎉

@pnbruckner pnbruckner deleted the script-modes branch March 11, 2020 23:40
@lock lock Bot locked and limited conversation to collaborators Mar 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants