Skip to content

Commit

Permalink
Split client-related logic out of the PantsDaemon class. (#9949)
Browse files Browse the repository at this point in the history
### Problem

The `PantsDaemon` class was playing double duty as both the entrypoint for the pantsd server, and as a launcher for the client. We will soon need to make significant changes there in order to support #8200 and #7654.

### Solution

Extract a `PantsDaemonProcessManager` base class for process metadata reads/writes and a `PantsDaemonClient` subclass to consume the metadata to decide whether to launch the server. This is 100% code moves... no logic changed.

### Result

The `PantsDaemon` class is now exclusively a server, and `PantsDaemonClient` is now exclusively a client.

[ci skip-rust-tests]
[ci skip-jvm-tests]
  • Loading branch information
stuhood authored Jun 3, 2020
1 parent bef71b2 commit ea27e7c
Show file tree
Hide file tree
Showing 8 changed files with 270 additions and 268 deletions.
2 changes: 1 addition & 1 deletion src/python/pants/bin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ python_library(
'src/python/pants/help',
'src/python/pants/init',
'src/python/pants/option',
'src/python/pants/pantsd:pants_daemon',
'src/python/pants/pantsd:pants_daemon_client',
'src/python/pants/reporting',
'src/python/pants/scm/subsystems:changed',
'src/python/pants/subsystem',
Expand Down
15 changes: 6 additions & 9 deletions src/python/pants/bin/remote_pants_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pants.java.nailgun_client import NailgunClient
from pants.java.nailgun_protocol import NailgunProtocol
from pants.option.options_bootstrapper import OptionsBootstrapper
from pants.pantsd.pants_daemon import PantsDaemon
from pants.pantsd.pants_daemon_client import PantsDaemonClient
from pants.util.dirutil import maybe_read_file

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -86,6 +86,7 @@ def __init__(
self._env = env
self._options_bootstrapper = options_bootstrapper
self._bootstrap_options = options_bootstrapper.bootstrap_options
self._client = PantsDaemonClient(self._bootstrap_options)
self._stdin = stdin or sys.stdin
self._stdout = stdout or sys.stdout.buffer
self._stderr = stderr or sys.stderr.buffer
Expand All @@ -107,7 +108,7 @@ def _backoff(attempt):
time.sleep(attempt + (attempt - 1))

def _run_pants_with_retry(
self, pantsd_handle: PantsDaemon.Handle, retries: int = 3
self, pantsd_handle: PantsDaemonClient.Handle, retries: int = 3
) -> ExitCode:
"""Runs pants remotely with retry and recovery for nascent executions.
Expand Down Expand Up @@ -137,7 +138,7 @@ def _run_pants_with_retry(
# another lifecycle operation is happening concurrently (incl teardown). To account for
# this, we won't begin attempting restarts until at least 1 second has passed (1 attempt).
if attempt > 1:
pantsd_handle = self._restart_pantsd()
pantsd_handle = self._client.restart()
attempt += 1
except NailgunClient.NailgunError as e:
# Ensure a newline.
Expand All @@ -146,7 +147,7 @@ def _run_pants_with_retry(
traceback = sys.exc_info()[2]
raise self._extract_remote_exception(pantsd_handle.pid, e).with_traceback(traceback)

def _connect_and_execute(self, pantsd_handle: PantsDaemon.Handle) -> ExitCode:
def _connect_and_execute(self, pantsd_handle: PantsDaemonClient.Handle) -> ExitCode:
port = pantsd_handle.port
pid = pantsd_handle.pid
# Merge the nailgun TTY capability environment variables with the passed environment dict.
Expand Down Expand Up @@ -204,9 +205,5 @@ def _extract_remote_exception(self, pantsd_pid, nailgun_error):
)
)

def _restart_pantsd(self):
return PantsDaemon.Factory.restart(options_bootstrapper=self._options_bootstrapper)

def run(self, start_time: float) -> ExitCode:
handle = PantsDaemon.Factory.maybe_launch(options_bootstrapper=self._options_bootstrapper)
return self._run_pants_with_retry(handle)
return self._run_pants_with_retry(self._client.maybe_launch())
8 changes: 4 additions & 4 deletions src/python/pants/core_tasks/pantsd_kill.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pants.base.exceptions import TaskError
from pants.option.options_bootstrapper import OptionsBootstrapper
from pants.pantsd.pants_daemon import PantsDaemon
from pants.pantsd.pants_daemon_client import PantsDaemonClient
from pants.pantsd.process_manager import ProcessManager
from pants.task.task import Task

Expand All @@ -13,8 +13,8 @@ class PantsDaemonKill(Task):

def execute(self):
try:
pantsd = PantsDaemon.Factory.create(OptionsBootstrapper.create(), full_init=False)
with pantsd.lifecycle_lock:
pantsd.terminate()
pantsd_client = PantsDaemonClient(OptionsBootstrapper.create().bootstrap_options)
with pantsd_client.lifecycle_lock:
pantsd_client.terminate()
except ProcessManager.NonResponsiveProcess as e:
raise TaskError("failure while terminating pantsd: {}".format(e))
14 changes: 12 additions & 2 deletions src/python/pants/pantsd/BUILD
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

python_library(
name = 'pants_daemon_client',
sources = ['pants_daemon_client.py'],
dependencies = [
'3rdparty/python:dataclasses',
':pants_daemon',
':process_manager',
'src/python/pants/option',
],
tags = {'partially_type_checked'},
)

python_library(
name = 'pants_daemon',
sources = ['pants_daemon.py'],
dependencies = [
'3rdparty/python:dataclasses',
'3rdparty/python:setproctitle',
':process_manager',
':watchman_launcher',
Expand All @@ -24,7 +35,6 @@ python_library(
'src/python/pants/pantsd/service:store_gc_service',
'src/python/pants/util:contextutil',
'src/python/pants/util:logging',
'src/python/pants/util:memo',
],
tags = {'partially_type_checked'},
)
Expand Down
Loading

0 comments on commit ea27e7c

Please sign in to comment.