Skip to content

Commit 3f2ba57

Browse files
author
Xuye (Chris) Qin
committed
Add actor driver & structure adjustment (mars-project#1925)
1 parent a67a5f6 commit 3f2ba57

File tree

10 files changed

+197
-34
lines changed

10 files changed

+197
-34
lines changed

mars/oscar/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from .api import actor_ref, create_actor, has_actor, destroy_actor
16-
from .core import Actor, ActorRef
15+
from .api import actor_ref, create_actor, has_actor, destroy_actor, Actor
16+
from .core import ActorRef
1717
from .context import get_context
1818
from .errors import ActorNotExist, ActorAlreadyExist
1919
from .utils import create_actor_ref

mars/oscar/api.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from typing import Any, Dict, Type, Tuple
16+
1517
from .context import get_context
18+
from .core import _Actor
1619

1720

1821
async def create_actor(actor_cls, *args, uid=None, address=None, **kwargs):
@@ -33,3 +36,48 @@ async def destroy_actor(actor_ref):
3336
def actor_ref(*args, **kwargs):
3437
ctx = get_context()
3538
return ctx.actor_ref(*args, **kwargs)
39+
40+
41+
class Actor(_Actor):
42+
def __new__(cls, *args, **kwargs):
43+
try:
44+
return _actor_implementation[cls](*args, **kwargs)
45+
except KeyError:
46+
return super().__new__(cls, *args, **kwargs)
47+
48+
async def __post_create__(self):
49+
"""
50+
Method called after actor creation
51+
"""
52+
return await super().__post_create__()
53+
54+
async def __pre_destroy__(self):
55+
"""
56+
Method called before actor destroy
57+
"""
58+
return await super().__pre_destroy__()
59+
60+
async def __on_receive__(self, message: Tuple[Any]):
61+
"""
62+
Handle message from other actors and dispatch them to user methods
63+
64+
Parameters
65+
----------
66+
message : tuple
67+
Message shall be (method_name,) + args + (kwargs,)
68+
"""
69+
return await super().__on_receive__(message)
70+
71+
72+
_actor_implementation: Dict[Type[Actor], Type[Actor]] = dict()
73+
74+
75+
def register_actor_implementation(actor_cls: Type[Actor], impl_cls: Type[Actor]):
76+
_actor_implementation[actor_cls] = impl_cls
77+
78+
79+
def unregister_actor_implementation(actor_cls: Type[Actor]):
80+
try:
81+
del _actor_implementation[actor_cls]
82+
except KeyError:
83+
pass

mars/oscar/backend.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 1999-2020 Alibaba Group Holding Ltd.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from abc import ABC, abstractmethod
16+
from typing import Type
17+
18+
from .context import register_backend_context
19+
from .driver import register_backend_driver
20+
21+
22+
__all__ = ["BaseActorBackend", "register_backend"]
23+
24+
25+
class BaseActorBackend(ABC):
26+
@staticmethod
27+
@abstractmethod
28+
def name():
29+
pass
30+
31+
@staticmethod
32+
@abstractmethod
33+
def get_context_cls():
34+
pass
35+
36+
@staticmethod
37+
@abstractmethod
38+
def get_driver_cls():
39+
pass
40+
41+
42+
def register_backend(backend_cls: Type[BaseActorBackend]):
43+
register_backend_context(backend_cls.name(), backend_cls.get_context_cls())
44+
register_backend_driver(backend_cls.name(), backend_cls.get_driver_cls())
45+
return backend_cls

mars/oscar/backends/mars/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,4 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from .pool import register_backend
16-
register_backend()
17-
del register_backend
15+
from .backend import MarsActorBackend
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 1999-2020 Alibaba Group Holding Ltd.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from ...backend import BaseActorBackend, register_backend
16+
from .driver import MarsActorDriver
17+
from .pool import MarsActorContext
18+
19+
20+
__all__ = ['MarsActorBackend']
21+
22+
23+
@register_backend
24+
class MarsActorBackend(BaseActorBackend):
25+
@staticmethod
26+
def name():
27+
# return None because Mars is default scheme
28+
return
29+
30+
@staticmethod
31+
def get_context_cls():
32+
return MarsActorContext
33+
34+
@staticmethod
35+
def get_driver_cls():
36+
return MarsActorDriver

mars/oscar/backends/mars/driver.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 1999-2020 Alibaba Group Holding Ltd.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from numbers import Number
16+
from typing import Dict
17+
18+
from ...driver import BaseActorDriver
19+
20+
21+
class MarsActorDriver(BaseActorDriver):
22+
def setup_cluster(self, address_to_resources: Dict[str, Dict[str, Number]]):
23+
# nothing need to be done in driver of Mars backend
24+
pass

mars/oscar/backends/mars/pool.pyx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,3 @@ cdef class MarsActorContext(BaseActorContext):
6363
raise ActorNotExist(f'Actor {actor_ref.uid} does not exist')
6464
ret = await actor.__on_receive__(message)
6565
return ret if wait_response else None
66-
67-
68-
def register_backend():
69-
from ...context import register_backend_context
70-
register_backend_context(None, MarsActorContext)

mars/oscar/context.pyx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414

1515
from urllib.parse import urlparse
1616

17-
from .core cimport _Actor, ActorRef
18-
from .errors import ActorAlreadyExist, ActorNotExist
17+
from .core cimport ActorRef
1918
from .utils cimport new_actor_id
2019

2120
cdef dict _backend_context_cls = dict()

mars/oscar/core.pyx

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -188,25 +188,3 @@ cdef class _Actor:
188188
if asyncio.iscoroutine(result):
189189
result = await result
190190
return await self._handle_actor_result(result)
191-
192-
193-
class Actor(_Actor):
194-
def __new__(cls, *args, **kwargs):
195-
try:
196-
return _actor_implementation[id(cls)](*args, **kwargs)
197-
except KeyError:
198-
return super().__new__(cls, *args, **kwargs)
199-
200-
201-
cdef dict _actor_implementation = dict()
202-
203-
204-
def register_actor_implementation(actor_cls, impl_cls):
205-
_actor_implementation[id(actor_cls)] = impl_cls
206-
207-
208-
def unregister_actor_implementation(actor_cls):
209-
try:
210-
del _actor_implementation[id(actor_cls)]
211-
except KeyError:
212-
pass

mars/oscar/driver.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 1999-2020 Alibaba Group Holding Ltd.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from abc import ABC, abstractmethod
16+
from numbers import Number
17+
from typing import Dict
18+
19+
20+
class BaseActorDriver(ABC):
21+
@abstractmethod
22+
def setup_cluster(self, address_to_resources: Dict[str, Dict[str, Number]]):
23+
"""
24+
Setup cluster according to given resources,
25+
resources is a dict, e.g. {'CPU': 3, 'GPU': 1}
26+
27+
Parameters
28+
----------
29+
address_to_resources: dict
30+
resources that required for each node.
31+
"""
32+
pass
33+
34+
35+
_backend_driver_cls: Dict = dict()
36+
37+
38+
def register_backend_driver(scheme, cls):
39+
assert issubclass(cls, BaseActorDriver)
40+
_backend_driver_cls[scheme] = cls

0 commit comments

Comments
 (0)