|
38 | 38 | make_engine_value_encoder, |
39 | 39 | ) |
40 | 40 | from .op import FunctionSpec |
41 | | -from .runtime import execution_context |
| 41 | +from .runtime import execution_context, to_async_call |
42 | 42 | from .setup import SetupChangeBundle |
43 | 43 | from .typing import analyze_type_info, encode_enriched_type |
| 44 | +from .query_handler import QueryHandlerInfo, QueryHandlerResultFields |
44 | 45 | from .validation import ( |
45 | 46 | validate_flow_name, |
46 | 47 | validate_full_flow_name, |
@@ -697,13 +698,15 @@ class Flow: |
697 | 698 | _engine_flow_creator: Callable[[], _engine.Flow] |
698 | 699 |
|
699 | 700 | _lazy_flow_lock: Lock |
| 701 | + _lazy_query_handler_args: list[tuple[Any, ...]] |
700 | 702 | _lazy_engine_flow: _engine.Flow | None = None |
701 | 703 |
|
702 | 704 | def __init__(self, name: str, engine_flow_creator: Callable[[], _engine.Flow]): |
703 | 705 | validate_flow_name(name) |
704 | 706 | self._name = name |
705 | 707 | self._engine_flow_creator = engine_flow_creator |
706 | 708 | self._lazy_flow_lock = Lock() |
| 709 | + self._lazy_query_handler_args = [] |
707 | 710 |
|
708 | 711 | def _render_spec(self, verbose: bool = False) -> Tree: |
709 | 712 | """ |
@@ -809,6 +812,9 @@ def _internal_flow(self) -> _engine.Flow: |
809 | 812 |
|
810 | 813 | engine_flow = self._engine_flow_creator() |
811 | 814 | self._lazy_engine_flow = engine_flow |
| 815 | + for args in self._lazy_query_handler_args: |
| 816 | + engine_flow.add_query_handler(*args) |
| 817 | + self._lazy_query_handler_args = [] |
812 | 818 |
|
813 | 819 | return engine_flow |
814 | 820 |
|
@@ -855,6 +861,43 @@ def close(self) -> None: |
855 | 861 | with _flows_lock: |
856 | 862 | del _flows[self.name] |
857 | 863 |
|
| 864 | + def add_query_handler( |
| 865 | + self, |
| 866 | + name: str, |
| 867 | + handler: Callable[[str], Any], |
| 868 | + /, |
| 869 | + *, |
| 870 | + result_fields: QueryHandlerResultFields | None = None, |
| 871 | + ) -> None: |
| 872 | + async_handler = to_async_call(handler) |
| 873 | + |
| 874 | + async def _handler(query: str) -> dict[str, Any]: |
| 875 | + handler_result = await async_handler(query) |
| 876 | + return { |
| 877 | + "results": dump_engine_object(handler_result.results), |
| 878 | + "query_info": dump_engine_object(handler_result.query_info), |
| 879 | + } |
| 880 | + |
| 881 | + handler_info = dump_engine_object(QueryHandlerInfo(result_fields=result_fields)) |
| 882 | + with self._lazy_flow_lock: |
| 883 | + if self._lazy_engine_flow is not None: |
| 884 | + self._lazy_engine_flow.add_query_handler(name, _handler, handler_info) |
| 885 | + else: |
| 886 | + self._lazy_query_handler_args.append((name, _handler, handler_info)) |
| 887 | + |
| 888 | + def query_handler( |
| 889 | + self, |
| 890 | + name: str | None = None, |
| 891 | + result_fields: QueryHandlerResultFields | None = None, |
| 892 | + ) -> Callable[[Callable[[str], Any]], Callable[[str], Any]]: |
| 893 | + def _inner(handler: Callable[[str], Any]) -> Callable[[str], Any]: |
| 894 | + self.add_query_handler( |
| 895 | + name or handler.__name__, handler, result_fields=result_fields |
| 896 | + ) |
| 897 | + return handler |
| 898 | + |
| 899 | + return _inner |
| 900 | + |
858 | 901 |
|
859 | 902 | def _create_lazy_flow( |
860 | 903 | name: str | None, fl_def: Callable[[FlowBuilder, DataScope], None] |
|
0 commit comments