From c9d78bea69ecffd8926919ed84dc8521835485cf Mon Sep 17 00:00:00 2001 From: Josh Karpel Date: Fri, 28 Jun 2024 20:32:53 -0500 Subject: [PATCH 1/3] print execution duration --- synthesize/execution.py | 8 ++++++++ synthesize/messages.py | 3 ++- synthesize/renderer.py | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/synthesize/execution.py b/synthesize/execution.py index bc21fd3..9fb85b6 100644 --- a/synthesize/execution.py +++ b/synthesize/execution.py @@ -4,9 +4,11 @@ from asyncio import Queue, Task, create_task from asyncio.subprocess import PIPE, STDOUT, Process, create_subprocess_exec from dataclasses import dataclass, field +from datetime import timedelta from pathlib import Path from signal import SIGKILL, SIGTERM from stat import S_IEXEC +from time import monotonic from synthesize.config import Args, Envs, FlowNode from synthesize.messages import ExecutionCompleted, ExecutionOutput, ExecutionStarted, Message @@ -39,6 +41,7 @@ class Execution: events: Queue[Message] = field(repr=False) process: Process + start_time: float reader: Task[None] @classmethod @@ -53,6 +56,8 @@ async def start( ) -> Execution: path = write_script(node=node, args=args, tmp_dir=tmp_dir) + start_time = monotonic() + process = await create_subprocess_exec( program=path, stdout=PIPE, @@ -86,6 +91,7 @@ async def start( node=node, events=events, process=process, + start_time=start_time, reader=reader, ) @@ -115,6 +121,7 @@ def kill(self) -> None: async def wait(self) -> Execution: exit_code = await self.process.wait() + end_time = monotonic() await self.reader @@ -123,6 +130,7 @@ async def wait(self) -> Execution: node=self.node, pid=self.pid, exit_code=exit_code, + duration=timedelta(seconds=end_time - self.start_time), ) ) diff --git a/synthesize/messages.py b/synthesize/messages.py index 5fddac6..23f2bbb 100644 --- a/synthesize/messages.py +++ b/synthesize/messages.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timedelta from pydantic import Field from watchfiles import Change @@ -20,6 +20,7 @@ class ExecutionCompleted(Message): node: FlowNode pid: int exit_code: int + duration: timedelta class ExecutionOutput(Message): diff --git a/synthesize/renderer.py b/synthesize/renderer.py index 6bb4adc..9ff2af0 100644 --- a/synthesize/renderer.py +++ b/synthesize/renderer.py @@ -120,11 +120,12 @@ def handle_lifecycle_message( (node.id, node.color), f" started (pid {pid})", ) - case ExecutionCompleted(node=node, pid=pid, exit_code=exit_code): + case ExecutionCompleted(node=node, pid=pid, exit_code=exit_code, duration=duration): parts = ( (node.id, node.color), f" (pid {pid}) exited with code ", (str(exit_code), "green" if exit_code == 0 else "red"), + f" in {duration.total_seconds() :.3f} seconds", ) case WatchPathChanged(node=node): changes = Text(" ").join( From 2ad69f025c6699d8dcdda2c91caca83867383390 Mon Sep 17 00:00:00 2001 From: Josh Karpel Date: Fri, 28 Jun 2024 20:34:06 -0500 Subject: [PATCH 2/3] changelog --- docs/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index addd374..3533eb1 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -21,6 +21,8 @@ Reorganized configuration to separate targets, triggers (formerly "lifecycles"), and flows (graphs of targets and triggers)." +- [#41](https://github.com/JoshKarpel/synthesize/pull/41) + Execution duration is printed in the completion message. ## `0.0.2` From 94572b6b7cf5d379c83bacb680c35dfa1abbbe54 Mon Sep 17 00:00:00 2001 From: Josh Karpel Date: Fri, 28 Jun 2024 20:35:14 -0500 Subject: [PATCH 3/3] test --- tests/test_execution.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_execution.py b/tests/test_execution.py index f98fda7..2574906 100644 --- a/tests/test_execution.py +++ b/tests/test_execution.py @@ -49,6 +49,7 @@ async def test_execution_lifecycle(tmp_path: Path) -> None: assert msg.node is node assert msg.pid == ex.pid assert msg.exit_code == ex.exit_code == 0 + assert msg.duration.total_seconds() > 0 async def test_termination_before_completion(tmp_path: Path) -> None: