Add test
This commit is contained in:
parent
4e4e2b036b
commit
0e7ee94574
|
@ -108,7 +108,7 @@ class WorkerProcess:
|
|||
)
|
||||
self.set_state(ProcessState.RESTARTING, force=True)
|
||||
if self.restart_order is RestartOrder.SHUTDOWN_FIRST:
|
||||
self._current_process.terminate()
|
||||
self._terminate_now()
|
||||
else:
|
||||
self._old_process = self._current_process
|
||||
self.kwargs.update(
|
||||
|
@ -121,8 +121,7 @@ class WorkerProcess:
|
|||
raise RuntimeError("Restart failed")
|
||||
|
||||
if self.restart_order is RestartOrder.STARTUP_FIRST:
|
||||
termination_thread = Thread(target=self.wait_to_terminate)
|
||||
termination_thread.start()
|
||||
self._terminate_soon()
|
||||
|
||||
self.worker_state[self.name] = {
|
||||
**self.worker_state[self.name],
|
||||
|
@ -131,7 +130,28 @@ class WorkerProcess:
|
|||
"restart_at": get_now(),
|
||||
}
|
||||
|
||||
def wait_to_terminate(self):
|
||||
def _terminate_now(self):
|
||||
logger.debug(
|
||||
f"{Colors.BLUE}Begin restart termination: "
|
||||
f"{Colors.BOLD}{Colors.SANIC}"
|
||||
f"%s {Colors.BLUE}[%s]{Colors.END}",
|
||||
self.name,
|
||||
self._current_process.pid,
|
||||
)
|
||||
self._current_process.terminate()
|
||||
|
||||
def _terminate_soon(self):
|
||||
logger.debug(
|
||||
f"{Colors.BLUE}Begin restart termination: "
|
||||
f"{Colors.BOLD}{Colors.SANIC}"
|
||||
f"%s {Colors.BLUE}[%s]{Colors.END}",
|
||||
self.name,
|
||||
self._current_process.pid,
|
||||
)
|
||||
termination_thread = Thread(target=self._wait_to_terminate)
|
||||
termination_thread.start()
|
||||
|
||||
def _wait_to_terminate(self):
|
||||
# TODO: Add a timeout?
|
||||
while self.state is not ProcessState.ACKED:
|
||||
...
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import re
|
||||
import signal
|
||||
import threading
|
||||
|
||||
from asyncio import Event
|
||||
from logging import DEBUG
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from sanic.app import Sanic
|
||||
from sanic.constants import RestartOrder
|
||||
from sanic.worker.loader import AppLoader
|
||||
from sanic.worker.process import ProcessState, WorkerProcess
|
||||
from sanic.worker.reloader import Reloader
|
||||
|
||||
|
||||
|
@ -154,3 +159,58 @@ def test_check_file(tmp_path):
|
|||
assert Reloader.check_file(current, mtimes) is False
|
||||
mtimes[current] = mtimes[current] - 1
|
||||
assert Reloader.check_file(current, mtimes) is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"order,expected",
|
||||
(
|
||||
(
|
||||
"shutdown_first",
|
||||
[
|
||||
"Restarting a process",
|
||||
"Begin restart termination",
|
||||
"Starting a process",
|
||||
],
|
||||
),
|
||||
(
|
||||
"startup_first",
|
||||
[
|
||||
"Restarting a process",
|
||||
"Starting a process",
|
||||
"Begin restart termination",
|
||||
"Process acked. Terminating",
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
def test_default_reload_shutdown_order(monkeypatch, caplog, order, expected):
|
||||
|
||||
current_process = Mock()
|
||||
worker_process = WorkerProcess(
|
||||
lambda **_: current_process,
|
||||
"Test",
|
||||
lambda **_: ...,
|
||||
{},
|
||||
{},
|
||||
RestartOrder[order.upper()],
|
||||
)
|
||||
|
||||
def start(self):
|
||||
worker_process.set_state(ProcessState.ACKED)
|
||||
self._target()
|
||||
|
||||
monkeypatch.setattr(threading.Thread, "start", start)
|
||||
|
||||
with caplog.at_level(DEBUG):
|
||||
worker_process.restart()
|
||||
|
||||
ansi = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
||||
|
||||
def clean(msg: str):
|
||||
msg, _ = ansi.sub("", msg).split(":", 1)
|
||||
return msg
|
||||
|
||||
debug = [clean(record[2]) for record in caplog.record_tuples]
|
||||
assert debug == expected
|
||||
current_process.start.assert_called_once()
|
||||
current_process.terminate.assert_called_once()
|
||||
|
|
Loading…
Reference in New Issue
Block a user