Skip to content

Commit

Permalink
Merge pull request #120 from vkottler/dev/2.8.3
Browse files Browse the repository at this point in the history
2.8.3 - Keep track of task overruns
  • Loading branch information
vkottler authored Sep 16, 2023
2 parents 7080fc8 + aaca0f4 commit bde8e08
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
- run: |
mk python-release owner=vkottler \
repo=runtimepy version=2.8.2
repo=runtimepy version=2.8.3
if: |
matrix.python-version == '3.11'
&& matrix.system == 'ubuntu-latest'
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
=====================================
generator=datazen
version=3.1.3
hash=d3f0baafa9c5baeb6d8d20b4ea391658
hash=fcc3bfa0c1f67dcd042d1dae9e51f0df
=====================================
-->

# runtimepy ([2.8.2](https://pypi.org/project/runtimepy/))
# runtimepy ([2.8.3](https://pypi.org/project/runtimepy/))

[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
Expand Down
2 changes: 1 addition & 1 deletion local/variables/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
major: 2
minor: 8
patch: 2
patch: 3
entry: runtimepy
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"

[project]
name = "runtimepy"
version = "2.8.2"
version = "2.8.3"
description = "A framework for implementing Python services."
readme = "README.md"
requires-python = ">=3.11"
Expand Down
4 changes: 2 additions & 2 deletions runtimepy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# =====================================
# generator=datazen
# version=3.1.3
# hash=da7c0ab24197420934cab6120b4e450e
# hash=28e92a234f304fdfaee160528a32928c
# =====================================

"""
Expand All @@ -10,7 +10,7 @@

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "2.8.2"
VERSION = "2.8.3"

# runtimepy-specific content.
METRICS_NAME = "metrics"
7 changes: 6 additions & 1 deletion runtimepy/metrics/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# internal
from runtimepy.primitives import Double as _Double
from runtimepy.primitives import Float as _Float
from runtimepy.primitives import Uint16 as _Uint16
from runtimepy.primitives import Uint32 as _Uint32


Expand All @@ -24,13 +25,14 @@ class PeriodicTaskMetrics(NamedTuple):
average_s: _Float
max_s: _Float
min_s: _Float
overruns: _Uint16

@staticmethod
def create() -> "PeriodicTaskMetrics":
"""Create a new metrics instance."""

return PeriodicTaskMetrics(
_Uint32(), _Float(), _Float(), _Float(), _Float()
_Uint32(), _Float(), _Float(), _Float(), _Float(), _Uint16()
)

@contextmanager
Expand All @@ -40,6 +42,7 @@ def measure(
rate: RateTracker,
dispatch: MovingAverage,
iter_time: _Double,
period_s: float,
) -> Iterator[None]:
"""Measure the time spent yielding and update data."""

Expand All @@ -55,3 +58,5 @@ def measure(
self.average_s.raw.value = dispatch(iter_time.value)
self.max_s.raw.value = dispatch.max
self.min_s.raw.value = dispatch.min
if iter_time.value > period_s:
self.overruns.value += 1
1 change: 1 addition & 0 deletions runtimepy/mixins/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def register_task_metrics(
self.env.channel("average_s", metrics.average_s)
self.env.channel("max_s", metrics.max_s)
self.env.channel("min_s", metrics.min_s)
self.env.channel("overruns", metrics.overruns)

def register_connection_metrics(
self, metrics: ConnectionMetrics, namespace: str = METRICS_NAME
Expand Down
6 changes: 5 additions & 1 deletion runtimepy/task/basic/periodic.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ async def run(
# When paused, don't run the iteration itself.
if not self._paused:
with self.metrics.measure(
eloop, self._dispatch_rate, self._dispatch_time, iter_time
eloop,
self._dispatch_rate,
self._dispatch_time,
iter_time,
self.period_s.value,
):
self._enabled.raw.value = await _asyncio.shield(
self.dispatch()
Expand Down
11 changes: 11 additions & 0 deletions tests/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ async def dispatch(self) -> bool:
"""Dispatch an iteration of this task."""

self.logger.info("Iteration.")

return True


class OverrunTask(PeriodicTask):
"""A sample task."""

async def dispatch(self) -> bool:
"""Dispatch an iteration of this task."""

await asyncio.sleep(self.period_s.value * 2)
return True


Expand Down
21 changes: 19 additions & 2 deletions tests/task/basic/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,31 @@
from pytest import mark

# internal
from tests.resources import SampleTask
from tests.resources import OverrunTask, SampleTask

BASE_PERIOD = 0.05


@mark.asyncio
async def test_periodic_task_overrun():
"""Test that the overrun counter increments properly."""

task = OverrunTask("overrun")
await task.task(period_s=BASE_PERIOD)

# Allow it to run.
while task.metrics.dispatches.value == 0:
await asyncio.sleep(BASE_PERIOD)

await task.stop()
assert task.metrics.overruns.value > 0


@mark.asyncio
async def test_periodic_task_basic():
"""Test basic interactions with periodic tasks."""

base_period = 0.05
base_period = BASE_PERIOD

task = SampleTask("sample")

Expand Down

0 comments on commit bde8e08

Please sign in to comment.