Skip to content

Commit 70f619a

Browse files
authored
Fix discovery information for void args (#71)
1 parent 22051d5 commit 70f619a

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

python/restate/discovery.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ def __init__(self, required: bool, contentType: str, jsonSchema: Optional[Any] =
5454
self.jsonSchema = jsonSchema
5555

5656
class OutputPayload:
57-
def __init__(self, contentType: str, setContentTypeIfEmpty: bool, jsonSchema: Optional[Any] = None):
57+
def __init__(self, setContentTypeIfEmpty: bool, contentType: Optional[str] = None, jsonSchema: Optional[Any] = None):
5858
self.contentType = contentType
5959
self.setContentTypeIfEmpty = setContentTypeIfEmpty
6060
self.jsonSchema = jsonSchema
6161

6262
class Handler:
63-
def __init__(self, name: str, ty: Optional[ServiceHandlerType] = None, input: Optional[InputPayload] = None, output: Optional[OutputPayload] = None, description: Optional[str] = None, metadata: Optional[Dict[str, str]] = None):
63+
def __init__(self, name: str, ty: Optional[ServiceHandlerType] = None, input: Optional[InputPayload | Dict[str, str]] = None, output: Optional[OutputPayload] = None, description: Optional[str] = None, metadata: Optional[Dict[str, str]] = None):
6464
self.name = name
6565
self.ty = ty
6666
self.input = input
@@ -180,13 +180,20 @@ def compute_discovery(endpoint: RestateEndpoint, discovered_as : typing.Literal[
180180
else:
181181
ty = None
182182
# input
183-
inp = InputPayload(required=False,
184-
contentType=handler.handler_io.accept,
185-
jsonSchema=json_schema_from_type_hint(handler.handler_io.input_type))
183+
inp: Optional[InputPayload | Dict[str, str]] = None
184+
if handler.handler_io.input_type and handler.handler_io.input_type.is_void:
185+
inp = {}
186+
else:
187+
inp =InputPayload(required=False,
188+
contentType=handler.handler_io.accept,
189+
jsonSchema=json_schema_from_type_hint(handler.handler_io.input_type))
186190
# output
187-
out = OutputPayload(setContentTypeIfEmpty=False,
188-
contentType=handler.handler_io.content_type,
189-
jsonSchema=json_schema_from_type_hint(handler.handler_io.output_type))
191+
if handler.handler_io.output_type and handler.handler_io.output_type.is_void:
192+
out = OutputPayload(setContentTypeIfEmpty=False)
193+
else:
194+
out = OutputPayload(setContentTypeIfEmpty=False,
195+
contentType=handler.handler_io.content_type,
196+
jsonSchema=json_schema_from_type_hint(handler.handler_io.output_type))
190197
# add the handler
191198
service_handlers.append(Handler(name=handler.name,
192199
ty=ty,

python/restate/handler.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class TypeHint(Generic[T]):
4646
"""
4747
annotation: Optional[T] = None
4848
is_pydantic: bool = False
49+
is_void: bool = False
4950

5051
@dataclass
5152
class HandlerIO(Generic[I, O]):
@@ -74,21 +75,28 @@ def update_handler_io_with_type_hints(handler_io: HandlerIO[I, O], signature: Si
7475
* capture any Pydantic models (to be used later at discovery)
7576
* replace the default json serializer (is unchanged by a user) with a Pydantic serde
7677
"""
77-
annotation = list(signature.parameters.values())[-1].annotation
78-
handler_io.input_type = TypeHint(annotation=annotation, is_pydantic=False)
79-
80-
if is_pydantic(annotation):
81-
handler_io.input_type.is_pydantic = True
82-
if isinstance(handler_io.input_serde, DefaultSerde):
83-
handler_io.input_serde = PydanticJsonSerde(annotation)
78+
params = list(signature.parameters.values())
79+
if len(params) == 1:
80+
# if there is only one parameter, it is the context.
81+
handler_io.input_type = TypeHint(is_void=True)
82+
else:
83+
annotation = params[-1].annotation
84+
handler_io.input_type = TypeHint(annotation=annotation, is_pydantic=False)
85+
if is_pydantic(annotation):
86+
handler_io.input_type.is_pydantic = True
87+
if isinstance(handler_io.input_serde, DefaultSerde):
88+
handler_io.input_serde = PydanticJsonSerde(annotation)
8489

8590
annotation = signature.return_annotation
86-
handler_io.output_type = TypeHint(annotation=annotation, is_pydantic=False)
87-
88-
if is_pydantic(annotation):
89-
handler_io.output_type.is_pydantic=True
90-
if isinstance(handler_io.output_serde, DefaultSerde):
91-
handler_io.output_serde = PydanticJsonSerde(annotation)
91+
if annotation is None or annotation is Signature.empty:
92+
# if there is no return annotation, we assume it is void
93+
handler_io.output_type = TypeHint(is_void=True)
94+
else:
95+
handler_io.output_type = TypeHint(annotation=annotation, is_pydantic=False)
96+
if is_pydantic(annotation):
97+
handler_io.output_type.is_pydantic=True
98+
if isinstance(handler_io.output_serde, DefaultSerde):
99+
handler_io.output_serde = PydanticJsonSerde(annotation)
92100

93101
# pylint: disable=R0902
94102
@dataclass

test-services/services/failing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ async def failing_call_with_eventual_success(ctx: ObjectContext) -> int:
4040
raise ValueError(f"Failed at attempt: {failures}")
4141

4242
@failing.handler(name="terminallyFailingSideEffect")
43-
async def terminally_failing_side_effect(ctx: ObjectContext):
43+
async def terminally_failing_side_effect(ctx: ObjectContext, error_message: str):
4444

4545
def side_effect():
46-
raise TerminalError(message="failed side effect")
46+
raise TerminalError(message=error_message)
4747

4848
await ctx.run("sideEffect", side_effect)
4949
raise ValueError("Should not reach here")

0 commit comments

Comments
 (0)