Skip to content

Commit 743fab8

Browse files
committed
Error on mixed async/sync
Differential Revision: [D85090856](https://our.internmc.facebook.com/intern/diff/D85090856/) **NOTE FOR REVIEWERS**: This PR has internal Meta-specific changes or comments, please review them on [Phabricator](https://our.internmc.facebook.com/intern/diff/D85090856/)! ghstack-source-id: 317475369 Pull Request resolved: #1626
1 parent 073b963 commit 743fab8

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

python/monarch/_src/actor/actor_mesh.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,9 @@ def __init__(
11141114
self._inner: "ActorMeshProtocol" = inner
11151115
self._shape = shape
11161116
self._proc_mesh = proc_mesh
1117+
1118+
async_endpoints = []
1119+
sync_endpoints = []
11171120
for attr_name in dir(self._class):
11181121
attr_value = getattr(self._class, attr_name, None)
11191122
if isinstance(attr_value, EndpointProperty):
@@ -1133,6 +1136,17 @@ def __init__(
11331136
attr_value._explicit_response_port,
11341137
),
11351138
)
1139+
if inspect.iscoroutinefunction(attr_value._method):
1140+
async_endpoints.append(attr_name)
1141+
else:
1142+
sync_endpoints.append(attr_name)
1143+
1144+
if sync_endpoints and async_endpoints:
1145+
raise ValueError(
1146+
f"{self._class} mixes both async and sync endpoints."
1147+
"Synchronous endpoints cannot be mixed with async endpoints because they can cause the asyncio loop to deadlock if they wait."
1148+
f"sync: {sync_endpoints} async: {async_endpoints}"
1149+
)
11361150

11371151
def __getattr__(self, attr: str) -> NotAnEndpoint:
11381152
if attr in dir(self._class):

python/tests/test_python_actors.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,14 @@ async def incr(self):
8787
async def value(self) -> int:
8888
return self.v
8989

90+
91+
class SyncCounter(Actor):
92+
def __init__(self, c):
93+
self.c = c
94+
9095
@endpoint
9196
def value_sync_endpoint(self) -> int:
92-
return self.v
97+
return self.c.value.choose().get()
9398

9499

95100
class Indirect(Actor):
@@ -112,7 +117,8 @@ async def test_choose():
112117

113118
assert result == result2
114119

115-
result3 = await v.value_sync_endpoint.choose()
120+
v2 = proc.spawn("sync_counter", SyncCounter, v)
121+
result3 = v2.value_sync_endpoint.choose().get()
116122
assert_type(result, int)
117123
assert result2 == result3
118124

0 commit comments

Comments
 (0)