Skip to content

Commit aef8dd9

Browse files
committed
Remove Timer.periodic() and Timer.timeout()
These names proved to be too confusing for users. It seems like having a short name that can convey all the intricacies of timers in the async world is very difficult, so we better stop trying to hide the complexity and force users to read about and use missed tick policies explicitly. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 2477050 commit aef8dd9

File tree

1 file changed

+0
-169
lines changed

1 file changed

+0
-169
lines changed

src/frequenz/channels/timer.py

Lines changed: 0 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -581,175 +581,6 @@ def __init__( # pylint: disable=too-many-arguments
581581
if auto_start:
582582
self.reset(start_delay=start_delay)
583583

584-
# We need a noqa here because the docs have a Raises section but the documented
585-
# exceptions are raised indirectly.
586-
@classmethod
587-
def timeout( # noqa: DOC502
588-
cls,
589-
delay: timedelta,
590-
/,
591-
*,
592-
auto_start: bool = True,
593-
start_delay: timedelta = timedelta(0),
594-
loop: asyncio.AbstractEventLoop | None = None,
595-
) -> Timer:
596-
"""Create a timer useful for tracking timeouts.
597-
598-
A [timeout][frequenz.channels.timer.Timer.timeout] is
599-
a [`Timer`][frequenz.channels.timer.Timer] that
600-
[resets][frequenz.channels.timer.Timer.reset] automatically after it triggers,
601-
so it will trigger again after the selected interval, no matter what the current
602-
drift was. This means timeout timers will accumulate drift.
603-
604-
Tip:
605-
Timeouts are a shortcut to create
606-
a [`Timer`][frequenz.channels.timer.Timer] with the
607-
[`SkipMissedAndDrift`][frequenz.channels.timer.SkipMissedAndDrift] policy.
608-
609-
Example: Timeout example
610-
```python
611-
import asyncio
612-
from datetime import timedelta
613-
614-
from frequenz.channels import Anycast, select, selected_from
615-
from frequenz.channels.timer import Timer
616-
617-
618-
async def main() -> None:
619-
channel = Anycast[int](name="data-channel")
620-
data_receiver = channel.new_receiver()
621-
622-
timer = Timer.timeout(timedelta(seconds=1.0))
623-
624-
async for selected in select(data_receiver, timer):
625-
if selected_from(selected, data_receiver):
626-
print(f"Received data: {selected.value}")
627-
elif selected_from(selected, timer):
628-
drift = selected.value
629-
print(f"No data received for {timer.interval + drift} seconds, giving up")
630-
break
631-
632-
633-
asyncio.run(main())
634-
```
635-
636-
Args:
637-
delay: The time until the timer ticks. Must be at least
638-
1 microsecond.
639-
auto_start: Whether the timer should be started when the
640-
instance is created. This can only be `True` if there is
641-
already a running loop or an explicit `loop` that is running
642-
was passed.
643-
start_delay: The delay before the timer should start. If `auto_start` is
644-
`False`, an exception is raised. This has microseconds resolution,
645-
anything smaller than a microsecond means no delay.
646-
loop: The event loop to use to track time. If `None`,
647-
`asyncio.get_running_loop()` will be used.
648-
649-
Returns:
650-
The timer instance.
651-
652-
Raises:
653-
RuntimeError: if it was called without a loop and there is no
654-
running loop.
655-
ValueError: if `interval` is not positive or is smaller than 1
656-
microsecond; if `start_delay` is negative or `start_delay` was specified
657-
but `auto_start` is `False`.
658-
"""
659-
return Timer(
660-
delay,
661-
SkipMissedAndDrift(delay_tolerance=timedelta(0)),
662-
auto_start=auto_start,
663-
start_delay=start_delay,
664-
loop=loop,
665-
)
666-
667-
# We need a noqa here because the docs have a Raises section but the documented
668-
# exceptions are raised indirectly.
669-
@classmethod
670-
def periodic( # noqa: DOC502 pylint: disable=too-many-arguments
671-
cls,
672-
period: timedelta,
673-
/,
674-
*,
675-
skip_missed_ticks: bool = False,
676-
auto_start: bool = True,
677-
start_delay: timedelta = timedelta(0),
678-
loop: asyncio.AbstractEventLoop | None = None,
679-
) -> Timer:
680-
"""Create a periodic timer.
681-
682-
A [periodic timer][frequenz.channels.timer.Timer.periodic] is
683-
a [`Timer`][frequenz.channels.timer.Timer] that tries as hard as possible to
684-
trigger at regular intervals. This means that if the timer is delayed for any
685-
reason, it will trigger immediately and then try to catch up with the original
686-
schedule.
687-
688-
Optionally, a periodic timer can be configured to skip missed ticks and re-sync
689-
with the original schedule (`skip_missed_ticks` argument). This could be useful
690-
if you want the timer is as periodic as possible but if there are big delays you
691-
don't end up with big bursts.
692-
693-
Tip:
694-
Periodic timers are a shortcut to create
695-
a [`Timer`][frequenz.channels.timer.Timer] with either the
696-
[`TriggerAllMissed`][frequenz.channels.timer.TriggerAllMissed] policy (when
697-
`skip_missed_ticks` is `False`) or
698-
[`SkipMissedAndResync`][frequenz.channels.timer.SkipMissedAndResync]
699-
otherwise.
700-
701-
Example:
702-
```python
703-
import asyncio
704-
from datetime import datetime, timedelta
705-
706-
from frequenz.channels.timer import Timer
707-
708-
709-
async def main() -> None:
710-
async for drift in Timer.periodic(timedelta(seconds=1.0)):
711-
print(f"The timer has triggered at {datetime.now()} with a drift of {drift}")
712-
713-
714-
asyncio.run(main())
715-
```
716-
717-
Args:
718-
period: The time between timer ticks. Must be at least
719-
1 microsecond.
720-
skip_missed_ticks: Whether to skip missed ticks or trigger them
721-
all until it catches up.
722-
auto_start: Whether the timer should be started when the
723-
instance is created. This can only be `True` if there is
724-
already a running loop or an explicit `loop` that is running
725-
was passed.
726-
start_delay: The delay before the timer should start. If `auto_start` is
727-
`False`, an exception is raised. This has microseconds resolution,
728-
anything smaller than a microsecond means no delay.
729-
loop: The event loop to use to track time. If `None`,
730-
`asyncio.get_running_loop()` will be used.
731-
732-
Returns:
733-
The timer instance.
734-
735-
Raises:
736-
RuntimeError: if it was called without a loop and there is no
737-
running loop.
738-
ValueError: if `interval` is not positive or is smaller than 1
739-
microsecond; if `start_delay` is negative or `start_delay` was specified
740-
but `auto_start` is `False`.
741-
"""
742-
missed_tick_policy = (
743-
SkipMissedAndResync() if skip_missed_ticks else TriggerAllMissed()
744-
)
745-
return Timer(
746-
period,
747-
missed_tick_policy,
748-
auto_start=auto_start,
749-
start_delay=start_delay,
750-
loop=loop,
751-
)
752-
753584
@property
754585
def interval(self) -> timedelta:
755586
"""The interval between timer ticks.

0 commit comments

Comments
 (0)