Skip to content

Commit

Permalink
Add on_stop extension point
Browse files Browse the repository at this point in the history
  • Loading branch information
bmerry committed Jul 11, 2019
1 parent 5367319 commit 442be8c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
15 changes: 15 additions & 0 deletions aiokatcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,20 @@ def factory():
self._server = await self.loop.create_server(factory, self._host, self._port)
self._stopping = False

async def on_stop(self) -> None:
"""Extension point for subclasses to run shutdown code.
This is called after the TCP server has been shut down and all
in-flight requests have been completed or cancelled. Subclasses
should override this function rather than :meth:`stop` to run
late shutdown code because this is called *before* the flag is
set to wake up :meth:`join`.
It is only called if the server was running when :meth:`stop` was
called.
"""
pass

async def stop(self, cancel: bool = True) -> None:
"""Shut down the server.
Expand All @@ -328,6 +342,7 @@ async def stop(self, cancel: bool = True) -> None:
client.write_message(msg)
client.close()
await client.wait_closed()
await self.on_stop()
self._stopped.set()

def halt(self, cancel: bool = True) -> asyncio.Task:
Expand Down
4 changes: 4 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Changelog
=========

.. rubric:: Development version

- Add :meth:`.Server.on_stop`.

.. rubric:: Version 0.5.0

- Make :class:`~.SensorSet` more generic and move into :mod:`aiokatcp.sensor`
Expand Down
14 changes: 12 additions & 2 deletions doc/server/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,5 +234,15 @@ The latter is useful as a callback for a signal handler, e.g.
asyncio.get_event_loop().add_signal_handler(signal.SIGINT, server.halt)
The ``?halt`` request is implemented in terms of :meth:`~.DeviceServer.halt`
and hence :meth:`~.DeviceServer.stop`. Thus, additional shutdown behaviour can
be added to the server by overriding :meth:`~.DeviceServer.stop`.
and hence :meth:`~.DeviceServer.stop`.

One gotcha is that :meth:`~.DeviceServer.join` returns as soon as
:meth:`~.DeviceServer.stop` completes. This is a problem if you override
:meth:`~.DeviceServer.stop` to shut down other parts of your system after the
katcp server has stopped, because this code may only run *after*
:meth:`~.DeviceServer.join` returns (particularly if it is asynchronous
code). Instead, one can override :meth:`~.DeviceServer.on_stop`, which
is a coroutine that does nothing and is intended specifically for this
purpose. It is called by :meth:`~.DeviceServer.stop` after it has
completed its work, but before it signals :meth:`~.DeviceServer.join` to
wake up.

0 comments on commit 442be8c

Please sign in to comment.