I have a long running Actor that produces data that is then consumed by other Actors. For now, let’s mock this in a simple fashion:
@ray.remote
class Actor:
def __init__(self):
self.msg = "Hello, World!"
def say(self):
while True:
print(self.msg)
However, sometimes I want to change how this actor produces data. Naively, I write:
@ray.remote
class Actor:
def __init__(self):
self.msg = "Hello, World!"
def update(self):
self.msg = "Goodbye, World!"
def say(self):
print(self.msg)
# recur as a task so other tasks can run
self.say.remote()
This errors as self.say
is a normal function. So instead I write a way to capture the special say.remote
function:
import ray, time
ray.init()
@ray.remote
class Actor:
def __init__(self):
self.msg = "Hello, World!"
self._say = None
def update(self):
self.msg = "Goodbye, World!"
def say(self, say_remote):
print(self.msg)
say_remote(say_remote)
actor = Actor.remote()
actor.say.remote(actor.say.remote)
time.sleep(2)
actor.update.remote()
time.sleep(5)
And this works! The terminal prints “Hello, World!” repeatedly for 2 seconds, and then prints “Goodbye, World!” for 4 seconds.
Questions:
- Is this okay to do for long running processes (i.e. no stackoverflow or issues?). in my real-world use-case, my
say
function takes about 1ms. - is there a better way to do this? I know could do with threads or async, but that seems messier imho.
This is admittedly a bit of a weird pattern, so would love any thoughts!