diff --git a/juju/model.py b/juju/model.py index 7d28154bc..2c0cabea8 100644 --- a/juju/model.py +++ b/juju/model.py @@ -3282,6 +3282,7 @@ async def new_wait_for_idle( ) apps = apps or list(self.applications) idle_times: dict[str, datetime] = {} + xidle_times: dict[str, datetime] = {} deadline = None if timeout is None else time.monotonic() + timeout @@ -3290,7 +3291,7 @@ async def new_wait_for_idle( expected_idle_since = xnow - timedelta(seconds=idle_period) full_status = await self.get_status() - rv, _ustat = _check_idle( + rv, ustat = _check_idle( full_status, apps=apps, raise_on_error=raise_on_error, @@ -3304,6 +3305,55 @@ async def new_wait_for_idle( now=xnow, expected_idle_since=expected_idle_since, ) + + if rv: + assert ustat + + if ustat: + xrv = True + + for name in ustat.units: + xidle_times.setdefault(name, xnow) + + for name in ustat.busy_units: + xidle_times[name] = xnow + + for app_name in apps: + ready_units = [ + n for n in ustat.ready_units if n.startswith(f"{app_name}/") + ] + if ( + wait_for_exact_units is None + and len(ready_units) < _wait_for_units + ): + logger.info( + "Waiting for app %r units %s >= %s", + app_name, + len(ustat.ready_units), + _wait_for_units, + ) + xrv = False + + if ( + wait_for_exact_units is not None + and len(ready_units) != wait_for_exact_units + ): + logger.info( + "Waiting for app %r units %s == %s", + app_name, + len(ready_units), + wait_for_exact_units, + ) + xrv = False + + if busy := [ + n for n, t in xidle_times.items() if expected_idle_since < t + ]: + logger.info("Waiting for %s to be idle enough", busy) + xrv = False + + assert xrv == rv + if rv: break @@ -3421,7 +3471,7 @@ def _check_idle( if wait_for_exact_units is None and len(ready_units) < _wait_for_units: logger.info( - "Waiting for app %r units %s/%s", + "Waiting for app %r units %s >= %s", app_name, len(ready_units), _wait_for_units, @@ -3433,10 +3483,10 @@ def _check_idle( and len(ready_units) != wait_for_exact_units ): logger.info( - "Waiting for app %r units %s/%s", + "Waiting for app %r units %s == %s", app_name, len(ready_units), - _wait_for_units, + wait_for_exact_units, ) return False, rv