Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print Execution duration in completion message #41

Merged
merged 3 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
8 changes: 8 additions & 0 deletions synthesize/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -39,6 +41,7 @@ class Execution:
events: Queue[Message] = field(repr=False)

process: Process
start_time: float
reader: Task[None]

@classmethod
Expand All @@ -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,
Expand Down Expand Up @@ -86,6 +91,7 @@ async def start(
node=node,
events=events,
process=process,
start_time=start_time,
reader=reader,
)

Expand Down Expand Up @@ -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

Expand All @@ -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),
)
)

Expand Down
3 changes: 2 additions & 1 deletion synthesize/messages.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta

from pydantic import Field
from watchfiles import Change
Expand All @@ -20,6 +20,7 @@ class ExecutionCompleted(Message):
node: FlowNode
pid: int
exit_code: int
duration: timedelta


class ExecutionOutput(Message):
Expand Down
3 changes: 2 additions & 1 deletion synthesize/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions tests/test_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading