19
19
import os
20
20
import mimetypes
21
21
import aiofiles
22
- from typing import List , Union , Callable , Dict , Awaitable , Optional , Mapping , cast
22
+ from typing import List , Union , Callable , Dict , Awaitable , Optional , Mapping , cast , TypeVar
23
23
from abc import abstractmethod , ABC
24
24
25
25
from ._ffi_client import FfiClient , FfiHandle
@@ -144,6 +144,12 @@ def disconnect_reason(
144
144
return self ._info .disconnect_reason
145
145
146
146
147
+ RpcHandler = Callable [["RpcInvocationData" ], Union [Awaitable [Optional [str ]], Optional [str ]]]
148
+ F = TypeVar (
149
+ "F" , bound = Callable [[RpcInvocationData ], Union [Awaitable [Optional [str ]], Optional [str ]]]
150
+ )
151
+
152
+
147
153
class LocalParticipant (Participant ):
148
154
"""Represents the local participant in a room."""
149
155
@@ -155,9 +161,7 @@ def __init__(
155
161
super ().__init__ (owned_info )
156
162
self ._room_queue = room_queue
157
163
self ._track_publications : dict [str , LocalTrackPublication ] = {} # type: ignore
158
- self ._rpc_handlers : Dict [
159
- str , Callable [[RpcInvocationData ], Union [Awaitable [str ], str ]]
160
- ] = {}
164
+ self ._rpc_handlers : Dict [str , RpcHandler ] = {}
161
165
162
166
@property
163
167
def track_publications (self ) -> Mapping [str , LocalTrackPublication ]:
@@ -328,8 +332,8 @@ async def perform_rpc(
328
332
def register_rpc_method (
329
333
self ,
330
334
method_name : str ,
331
- handler : Optional [Callable [[ RpcInvocationData ], Union [ Awaitable [ str ], str ]] ] = None ,
332
- ) -> Union [None , Callable ]:
335
+ handler : Optional [F ] = None ,
336
+ ) -> Union [F , Callable [[ F ], F ] ]:
333
337
"""
334
338
Establishes the participant as a receiver for calls of the specified RPC method.
335
339
Can be used either as a decorator or a regular method.
@@ -366,18 +370,17 @@ async def greet_handler(data: RpcInvocationData) -> str:
366
370
room.local_participant.register_rpc_method('greet', greet_handler)
367
371
"""
368
372
369
- def register (handler_func ) :
373
+ def register (handler_func : F ) -> F :
370
374
self ._rpc_handlers [method_name ] = handler_func
371
375
req = proto_ffi .FfiRequest ()
372
376
req .register_rpc_method .local_participant_handle = self ._ffi_handle .handle
373
377
req .register_rpc_method .method = method_name
374
378
FfiClient .instance .request (req )
379
+ return handler_func
375
380
376
381
if handler is not None :
377
- register (handler )
378
- return None
382
+ return register (handler )
379
383
else :
380
- # Called as a decorator
381
384
return register
382
385
383
386
def unregister_rpc_method (self , method : str ) -> None :
@@ -438,33 +441,22 @@ async def _handle_rpc_method_invocation(
438
441
else :
439
442
try :
440
443
if asyncio .iscoroutinefunction (handler ):
441
- async_handler = cast (Callable [[RpcInvocationData ], Awaitable [str ]], handler )
442
-
443
- async def run_handler ():
444
- try :
445
- return await async_handler (params )
446
- except asyncio .CancelledError :
447
- # This will be caught by the outer try-except if it's due to timeout
448
- raise
449
-
450
444
try :
451
445
response_payload = await asyncio .wait_for (
452
- run_handler ( ), timeout = response_timeout
446
+ handler ( params ), timeout = response_timeout
453
447
)
454
448
except asyncio .TimeoutError :
455
449
raise RpcError ._built_in (RpcError .ErrorCode .RESPONSE_TIMEOUT )
456
450
except asyncio .CancelledError :
457
451
raise RpcError ._built_in (RpcError .ErrorCode .RECIPIENT_DISCONNECTED )
458
452
else :
459
- sync_handler = cast (Callable [[RpcInvocationData ], str ], handler )
460
- response_payload = sync_handler (params )
453
+ response_payload = cast (Optional [str ], handler (params ))
461
454
except RpcError as error :
462
455
response_error = error
463
- except Exception as error :
456
+ except Exception :
464
457
logger .exception (
465
458
f"Uncaught error returned by RPC handler for { method } . "
466
459
"Returning APPLICATION_ERROR instead. "
467
- f"Original error: { error } "
468
460
)
469
461
response_error = RpcError ._built_in (RpcError .ErrorCode .APPLICATION_ERROR )
470
462
@@ -480,8 +472,8 @@ async def run_handler():
480
472
res = FfiClient .instance .request (req )
481
473
482
474
if res .rpc_method_invocation_response .error :
483
- message = res .rpc_method_invocation_response .error
484
- logger .exception (f"error sending rpc method invocation response: { message } " )
475
+ err = res .rpc_method_invocation_response .error
476
+ logger .error (f"error sending rpc method invocation response: { err } " )
485
477
486
478
async def set_metadata (self , metadata : str ) -> None :
487
479
"""
0 commit comments