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

make sure futures can be cancelled #797

Merged
merged 1 commit into from Oct 19, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 20 additions & 6 deletions kubespawner/spawner.py
Expand Up @@ -2467,11 +2467,18 @@ async def _stop_all_reflectors(cls):
reflector = cls.reflectors.pop(key)
tasks.append(reflector.stop())

# make sure all tasks are Futures so we can cancel them later
# in case of error
futures = [asyncio.ensure_future(task) for task in tasks]
try:
await asyncio.gather(*tasks)
await asyncio.gather(*futures)
except Exception:
for task in tasks:
task.cancel()
# cancel any unfinished tasks before re-raising
# because gather doesn't cancel unfinished tasks.
# TaskGroup would do this cancel for us, but requires Python 3.11
for future in futures:
if not future.done():
future.cancel()
raise

def start(self):
Expand Down Expand Up @@ -2659,14 +2666,21 @@ async def _start(self):

# namespace can be changed via kubespawner_override, start watching pods only after
# load_user_options() is called
start_futures = [self._start_watching_pods()]
start_tasks = [self._start_watching_pods()]
if self.events_enabled:
start_futures.append(self._start_watching_events())
start_tasks.append(self._start_watching_events())
# create Futures for coroutines so we can cancel them
# in case of an error
start_futures = [asyncio.ensure_future(task) for task in start_tasks]
try:
await asyncio.gather(*start_futures)
except Exception:
# cancel any unfinished tasks before re-raising
# because gather doesn't cancel unfinished tasks.
# TaskGroup would do this cancel for us, but requires Python 3.11
for future in start_futures:
future.cancel()
if not future.done():
future.cancel()
raise

# record latest event so we don't include old
Expand Down