A countdown as a loop. Simple, but the function can run for minutes, hours, or days, despite restarts.
from __future__ import annotations
import asyncio
import os
from typing import TYPE_CHECKING
from resonate.resonate import Resonate
if TYPE_CHECKING:
from resonate.context import Context
async def countdown(ctx: Context, count: int, delay: int) -> None:
for i in range(count, 0, -1):
# Run a function, persist its result
await ctx.run(ntfy, i)
# Sleep
await ctx.sleep(delay)
print("Done!")
async def ntfy(_: Context, i: int) -> None:
print(f"Countdown: {i}")
async def main() -> None:
r = Resonate(url=os.environ.get("RESONATE_URL", "http://localhost:8001"))
r.register(countdown)
r.register(ntfy)
await asyncio.Event().wait()
if __name__ == "__main__":
asyncio.run(main())brew install resonatehq/tap/resonatepip install resonate-sdkresonate devpython countdown.pyActivate the function with execution ID countdown.1:
resonate invoke countdown.1 --func countdown --arg 5 --arg 60You will see the countdown in the terminal
python countdown.py
Countdown: 5
Countdown: 4
Countdown: 3
Countdown: 2
Countdown: 1
Done!After starting the function, inspect the current state of the execution using the resonate tree command. The tree command visualizes the call graph of the function execution as a graph of durable promises.
resonate tree countdown.1Now try killing the worker mid-countdown and restarting. The countdown picks up right where it left off without missing a beat.