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

Feat/async start of serve #15972

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions src/prefect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
Transaction,
unmapped,
serve,
aserve,
deploy,
pause_flow_run,
resume_flow_run,
Expand Down Expand Up @@ -66,6 +67,7 @@
"Transaction": (__spec__.parent, ".main"),
"unmapped": (__spec__.parent, ".main"),
"serve": (__spec__.parent, ".main"),
"aserve": (__spec__.parent, ".main"),
"deploy": (__spec__.parent, ".main"),
"pause_flow_run": (__spec__.parent, ".main"),
"resume_flow_run": (__spec__.parent, ".main"),
Expand All @@ -86,6 +88,7 @@
"Transaction",
"unmapped",
"serve",
"aserve",
"deploy",
"pause_flow_run",
"resume_flow_run",
Expand Down
132 changes: 103 additions & 29 deletions src/prefect/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -1812,8 +1812,6 @@ def my_other_flow(name):
serve(hello_deploy, bye_deploy)
```
"""
from rich.console import Console, Group
from rich.table import Table

from prefect.runner import Runner

Expand All @@ -1822,33 +1820,7 @@ def my_other_flow(name):
runner.add_deployment(deployment)

if print_starting_message:
help_message_top = (
"[green]Your deployments are being served and polling for"
" scheduled runs!\n[/]"
)

table = Table(title="Deployments", show_header=False)

table.add_column(style="blue", no_wrap=True)

for deployment in args:
table.add_row(f"{deployment.flow_name}/{deployment.name}")

help_message_bottom = (
"\nTo trigger any of these deployments, use the"
" following command:\n[blue]\n\t$ prefect deployment run"
" [DEPLOYMENT_NAME]\n[/]"
)
if PREFECT_UI_URL:
help_message_bottom += (
"\nYou can also trigger your deployments via the Prefect UI:"
f" [blue]{PREFECT_UI_URL.value()}/deployments[/]\n"
)

console = Console()
console.print(
Group(help_message_top, table, help_message_bottom), soft_wrap=True
)
display_start_message(*args)

try:
loop = asyncio.get_running_loop()
Expand All @@ -1869,6 +1841,108 @@ def my_other_flow(name):
loop.stop()


async def aserve(
*args: "RunnerDeployment",
pause_on_shutdown: bool = True,
print_starting_message: bool = True,
limit: Optional[int] = None,
**kwargs,
):
"""
Serve the provided list of deployments with the possibility of asynchronous context initialization.

Args:
*args: A list of deployments to serve.
pause_on_shutdown: A boolean for whether or not to automatically pause
deployment schedules on shutdown.
print_starting_message: Whether or not to print message to the console
on startup.
limit: The maximum number of runs that can be executed concurrently.
**kwargs: Additional keyword arguments to pass to the runner.

Examples:
Prepare deployment and asynchronous initialization function and serve them:

```python
import asyncio
import datetime

from prefect import flow, aserve, get_client


async def init():
await set_concurrency_limit()


async def set_concurrency_limit():
async with get_client() as client:
await client.create_concurrency_limit(tag='dev', concurrency_limit=3)


@flow
async def my_flow(name):
print(f"hello {name}")


async def main():
# Initialization function
await init()

# Run once a day
hello_deploy = await my_flow.to_deployment(
"hello", tags=["dev"], interval=datetime.timedelta(days=1)
)

await aserve(hello_deploy)


if __name__ == "__main__":
asyncio.run(main())
"""

from prefect.runner import Runner

runner = Runner(pause_on_shutdown=pause_on_shutdown, limit=limit, **kwargs)
for deployment in args:
await runner.add_deployment(deployment)

if print_starting_message:
display_start_message(*args)

await runner.start()


def display_start_message(*args: "RunnerDeployment"):
from rich.console import Console, Group
from rich.table import Table

help_message_top = (
"[green]Your deployments are being served and polling for"
" scheduled runs!\n[/]"
)

table = Table(title="Deployments", show_header=False)

table.add_column(style="blue", no_wrap=True)

for deployment in args:
table.add_row(f"{deployment.flow_name}/{deployment.name}")

help_message_bottom = (
"\nTo trigger any of these deployments, use the"
" following command:\n[blue]\n\t$ prefect deployment run"
" [DEPLOYMENT_NAME]\n[/]"
)
if PREFECT_UI_URL:
help_message_bottom += (
"\nYou can also trigger your deployments via the Prefect UI:"
f" [blue]{PREFECT_UI_URL.value()}/deployments[/]\n"
)

console = Console()
console.print(Group(help_message_top, table, help_message_bottom), soft_wrap=True)


@client_injector
async def load_flow_from_flow_run(
client: "PrefectClient",
Expand Down
3 changes: 2 additions & 1 deletion src/prefect/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from prefect.deployments import deploy
from prefect.states import State
from prefect.logging import get_run_logger
from prefect.flows import flow, Flow, serve
from prefect.flows import flow, Flow, serve, aserve
from prefect.transactions import Transaction
from prefect.tasks import task, Task
from prefect.context import tags
Expand Down Expand Up @@ -84,6 +84,7 @@
"Transaction",
"unmapped",
"serve",
"aserve",
"deploy",
"pause_flow_run",
"resume_flow_run",
Expand Down
Loading