Skip to content

Commit cd534a6

Browse files
committed
Fix test run w/ Go server/worker
1 parent 361be4a commit cd534a6

File tree

5 files changed

+27
-92
lines changed

5 files changed

+27
-92
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ temporalio/api/*
66
temporalio/bridge/proto/*
77
!temporalio/bridge/proto/__init__.py
88
temporalio/bridge/target/
9+
/tests/fixtures/golangserver/golangserver
10+
/tests/fixtures/golangworker/golangworker

poetry.lock

Lines changed: 1 addition & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ isort = "^5.10.1"
2424
maturin = "^0.12.6"
2525
mypy = "^0.931"
2626
mypy-protobuf = "^3.2.0"
27-
psutil = "^5.9.0"
2827
pydocstyle = "^6.1.1"
2928
pytest = "^6.2.5"
3029
pytest-asyncio = "^0.18.0"

tests/conftest.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
def event_loop():
1010
# See https://github.com/pytest-dev/pytest-asyncio/issues/68
1111
# See https://github.com/pytest-dev/pytest-asyncio/issues/257
12-
policy = asyncio.get_event_loop_policy()
13-
loop = policy.new_event_loop()
12+
loop = asyncio.get_event_loop_policy().new_event_loop()
1413
yield loop
1514
loop.close()
16-
policy.set_event_loop(loop)

tests/fixtures/utils.py

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import asyncio
22
import logging
33
import os
4-
import signal
4+
import subprocess
55
import uuid
66
from abc import ABC, abstractmethod
77
from dataclasses import dataclass
88
from typing import Any, AsyncGenerator, Optional
99

10-
import psutil
1110
import pytest_asyncio
1211

1312
import temporalio.api.workflowservice.v1
@@ -60,15 +59,11 @@ async def start() -> "ExternalGolangServer":
6059
namespace = f"test-namespace-{uuid.uuid4()}"
6160
# TODO(cretz): Make this configurable?
6261
port = "9233"
63-
process = await asyncio.create_subprocess_exec(
64-
"go",
65-
"run",
66-
".",
62+
process = await start_external_go_process(
63+
os.path.join(os.path.dirname(__file__), "golangserver"),
64+
"golangserver",
6765
port,
6866
namespace,
69-
cwd=os.path.abspath(
70-
os.path.join(os.path.dirname(__file__), "golangserver")
71-
),
7267
)
7368
server = ExternalGolangServer(f"localhost:{port}", namespace, process)
7469
# Try to get the client multiple times to check whether server is online
@@ -99,7 +94,7 @@ def namespace(self) -> str:
9994
return self._namespace
10095

10196
async def close(self):
102-
kill_proc_tree(self._process.pid)
97+
self._process.terminate()
10398
await self._process.wait()
10499

105100

@@ -143,19 +138,15 @@ async def close(self):
143138
class ExternalGolangWorker(Worker):
144139
@staticmethod
145140
async def start(host_port: str, namespace: str) -> "ExternalGolangWorker":
146-
task_queue = uuid.uuid4()
147-
process = await asyncio.create_subprocess_exec(
148-
"go",
149-
"run",
150-
".",
141+
task_queue = str(uuid.uuid4())
142+
process = await start_external_go_process(
143+
os.path.join(os.path.dirname(__file__), "golangworker"),
144+
"golangworker",
151145
host_port,
152146
namespace,
153-
str(task_queue),
154-
cwd=os.path.abspath(
155-
os.path.join(os.path.dirname(__file__), "golangworker")
156-
),
147+
task_queue,
157148
)
158-
return ExternalGolangWorker(str(task_queue), process)
149+
return ExternalGolangWorker(task_queue, process)
159150

160151
def __init__(self, task_queue: str, process: asyncio.subprocess.Process) -> None:
161152
super().__init__()
@@ -167,7 +158,7 @@ def task_queue(self) -> str:
167158
return self._task_queue
168159

169160
async def close(self):
170-
kill_proc_tree(self._process.pid)
161+
self._process.terminate()
171162
await self._process.wait()
172163

173164

@@ -178,24 +169,14 @@ async def worker(server: Server) -> AsyncGenerator[Worker, None]:
178169
await worker.close()
179170

180171

181-
# See https://psutil.readthedocs.io/en/latest/#kill-process-tree
182-
def kill_proc_tree(
183-
pid, sig=signal.SIGTERM, include_parent=True, timeout=None, on_terminate=None
184-
):
185-
"""Kill a process tree (including grandchildren) with signal
186-
"sig" and return a (gone, still_alive) tuple.
187-
"on_terminate", if specified, is a callback function which is
188-
called as soon as a child terminates.
189-
"""
190-
assert pid != os.getpid(), "won't kill myself"
191-
parent = psutil.Process(pid)
192-
children = parent.children(recursive=True)
193-
if include_parent:
194-
children.append(parent)
195-
for p in children:
196-
try:
197-
p.send_signal(sig)
198-
except psutil.NoSuchProcess:
199-
pass
200-
gone, alive = psutil.wait_procs(children, timeout=timeout, callback=on_terminate)
201-
return (gone, alive)
172+
async def start_external_go_process(
173+
source_dir: str, exe_name: str, *args: str
174+
) -> asyncio.subprocess.Process:
175+
# First, build the executable. We accept the performance issues of building
176+
# this each run.
177+
logger.info("Building %s", exe_name)
178+
subprocess.run(["go", "build", "-o", exe_name, "."], cwd=source_dir, check=True)
179+
logger.info("Starting %s", exe_name)
180+
return await asyncio.create_subprocess_exec(
181+
os.path.join(source_dir, exe_name), *args
182+
)

0 commit comments

Comments
 (0)