44
55import os
66from concurrent import futures
7+ from contextlib import contextmanager
78from http .server import ThreadingHTTPServer
89from typing import Any , Callable , Coroutine , Optional , TypeVar , overload
910from urllib .parse import urlsplit
3738 "gather" ,
3839 "race" ,
3940 "run" ,
41+ "serve" ,
4042]
4143
4244
4648_registry : Optional [Registry ] = None
4749
4850
49- def _default_registry ():
51+ def default_registry ():
5052 global _registry
5153 if not _registry :
5254 _registry = Registry ()
@@ -62,10 +64,10 @@ def function(func: Callable[P, T]) -> Function[P, T]: ...
6264
6365
6466def function (func ):
65- return _default_registry ().function (func )
67+ return default_registry ().function (func )
6668
6769
68- def run (port : str = os . environ . get ( "DISPATCH_ENDPOINT_ADDR" , "localhost:8000" )) :
70+ def run (init : Callable [ P , T ], * args : P . args , ** kwargs : P . kwargs ) -> T :
6971 """Run the default dispatch server on the given port. The default server
7072 uses a function registry where functions tagged by the `@dispatch.function`
7173 decorator are registered.
@@ -75,12 +77,35 @@ def run(port: str = os.environ.get("DISPATCH_ENDPOINT_ADDR", "localhost:8000")):
7577 to the Dispatch bridge API.
7678
7779 Args:
78- port: The address to bind the server to. Defaults to the value of the
80+ entrypoint: The entrypoint function to run. Defaults to a no-op function.
81+
82+ args: Positional arguments to pass to the entrypoint.
83+
84+ kwargs: Keyword arguments to pass to the entrypoint.
85+
86+ Returns:
87+ The return value of the entrypoint function.
88+ """
89+ with serve ():
90+ return init (* args , ** kwargs )
91+
92+
93+ @contextmanager
94+ def serve (address : str = os .environ .get ("DISPATCH_ENDPOINT_ADDR" , "localhost:8000" )):
95+ """Returns a context manager managing the operation of a Disaptch server
96+ running on the given address. The server is initialized before the context
97+ manager yields, then runs forever until the the program is interrupted.
98+
99+ Args:
100+ address: The address to bind the server to. Defaults to the value of the
79101 DISPATCH_ENDPOINT_ADDR environment variable, or 'localhost:8000' if it
80102 wasn't set.
81103 """
82- print (f"Starting Dispatch server on { port } " )
83- parsed_url = urlsplit ("//" + port )
104+ parsed_url = urlsplit ("//" + address )
84105 server_address = (parsed_url .hostname or "" , parsed_url .port or 0 )
85- server = ThreadingHTTPServer (server_address , Dispatch (_default_registry ()))
86- server .serve_forever ()
106+ server = ThreadingHTTPServer (server_address , Dispatch (default_registry ()))
107+ try :
108+ yield server
109+ server .serve_forever ()
110+ finally :
111+ server .server_close ()
0 commit comments