async def main(): context = RootContext() props = Props.from_func(hello_function) pid = context.spawn(props) reply = await context.request_async(pid, HelloMessage('Hello')) print(reply)
async def test_reenter_after_can_do_action_for_task(): queue = Queue() async def actor(ctx): if ctx.message == 'hello1': async def target(): await asyncio.sleep(0.1) queue.put('bar') return 'hey1' async def action(result): queue.put('baz') await ctx.respond(result) ctx.reenter_after(target, action) elif ctx.message == 'hello2': queue.put('foo') await ctx.respond('hey2') props = Props.from_func(actor) pid = context.spawn(props) task1 = asyncio.ensure_future(context.request_async(pid, "hello1")) task2 = asyncio.ensure_future(context.request_async(pid, "hello2")) reply1 = await task1 reply2 = await task2 assert reply1 == 'hey1' assert reply2 == 'hey2' assert 'foo' == queue.get() assert 'bar' == queue.get() assert 'baz' == queue.get()
async def test_can_use_separate_stores(): threading_events = { 'process_started': threading.Event(), 'process_get_state': threading.Event(), 'process_get_index': threading.Event(), 'process_request_snapshot': threading.Event(), 'process_multiply': threading.Event() } actor_id = str(uuid.uuid4()) event_store = InMemoryProvider() snapshot_store = InMemoryProvider() props = Props.from_producer(lambda: ExamplePersistentActor( threading_events, event_store, snapshot_store, actor_id)).with_mailbox( MockMailbox) pid = root_context.spawn(props) await root_context.send(pid, Multiply(2)) threading_events['process_multiply'].wait() threading_events['process_multiply'].clear() event_store_messages = [] await event_store.get_events(actor_id, 0, 1, lambda msg: event_store_messages.append(msg)) assert len(event_store_messages) == 1 snapshot_store_messages = [] await snapshot_store.get_events( actor_id, 0, 1, lambda msg: snapshot_store_messages.append(msg)) assert len(snapshot_store_messages) == 0
async def setup(self) -> None: props = Props.from_producer(lambda: PidCacheWatcher()) \ .with_guardian_supervisor_strategy(Supervision.always_restart_strategy) self._watcher = GlobalRootContext.spawn_named(props, 'PidCacheWatcher') self._cluster_topology_evn_sub = GlobalEventStream.subscribe( self.process_member_status_event, type(AbstractMemberStatusEvent))
async def main(): context = RootContext() props = Props.from_producer(HelloActor) pid = context.spawn(props) await context.send(pid, HelloMessage('Hello World!')) input()
async def __process_start_loop_actor_message(self, context, message): if self._timer_started: return self._timer_started = True print('MyPersistenceActor - StartLoopActor') props = Props.from_producer(lambda: LoopActor()) self._loop_actor = context.spawn(props)
async def main(): tracer = init_jaeger_tracer() opentracing.set_global_tracer(tracer) context = RootContext() Serialization().register_file_descriptor(DESCRIPTOR) Remote().start("127.0.0.1", 8000) clients = [] async def process_message(ctx: AbstractContext): msg = ctx.message if isinstance(msg, Connect): print(f'Client {msg.sender} connected') clients.append(msg.sender) await ctx.send(msg.sender, Connected(message='Welcome!')) elif isinstance(msg, SayRequest): for client in clients: await ctx.send(client, SayResponse(user_name=msg.user_name, message=msg.message)) elif isinstance(msg, NickRequest): for client in clients: await ctx.send(client, NickResponse(old_user_name=msg.old_user_name, new_user_name=msg.new_user_name)) props = OpenTracingFactory.get_props_with_open_tracing(Props.from_func(process_message), span_setup, span_setup) context.spawn_named(props, 'chatserver') input()
async def test_pop_behavior_should_restore_pushed_behavior(): behavior = Behavior() async def func_1(ctx): if isinstance(ctx.message, str): async def func_2(ctx2): await ctx2.respond(42) behavior.unbecome_stacked() behavior.become_stacked(func_2) await ctx.respond(ctx.message) behavior.become(func_1) props = Props.from_func(behavior.receive_async) context = RootContext() pid = context.spawn(props) reply = await context.request_future(pid, "number") reply_after_push = await context.request_future(pid, None) reply_after_pop = await context.request_future( pid, "answertolifetheuniverseandeverything") assert reply + str( reply_after_push ) + reply_after_pop == "number42answertolifetheuniverseandeverything"
async def main(): context = RootContext() Serialization().register_file_descriptor(DESCRIPTOR) Remote().start("192.168.1.129", 12001) wg = asyncio.Event() message_count = 10000 props = Props.from_producer(lambda: LocalClient(0, message_count, wg, asyncio.get_event_loop())) pid = context.spawn(props) remote = PID(address="192.168.1.77:12000", id="remote") await context.request_future(remote, StartRemote(Sender=pid)) start = datetime.datetime.now() print('Starting to send') for i in range(message_count): await context.send(remote, Ping()) await wg.wait() elapsed = datetime.datetime.now() - start print(f'Elapsed {elapsed}') t = message_count * 2.0 / elapsed.total_seconds() print(f'Throughput {t} msg / sec') input()
async def test_request_actor_async_should_not_raise_timeout_exception_when_result_is_first( ): props = Props.from_func(hello_function) pid = context.spawn(props) reply = await context.request_async(pid, "hello", timedelta(seconds=1)) assert reply == "hey"
async def start(argv): tracer = init_jaeger_tracer() opentracing.set_global_tracer(tracer) middleware = open_tracing_middleware.open_tracing_sender_middleware(tracer) Serialization().register_file_descriptor(DESCRIPTOR) Remote().start("127.0.0.1", 12001) server = PID(address='127.0.0.1:8000', id='chatserver') context = RootContext(MessageHeader(), [middleware]) props = OpenTracingFactory.get_props_with_open_tracing(Props.from_func(process_message), span_setup, span_setup, tracer) client = context.spawn(props) await context.send(server, Connect(sender=client)) nick = 'Alex' while True: text = input() if text == '/exit': return elif text.startswith('/nick '): new_nick = text.split(' ')[1] await context.send(server, NickRequest(old_user_name=nick, new_user_name=new_nick)) nick = new_nick else: await context.send(server, SayRequest(user_name=nick, message=text))
def get_props_with_open_tracing(props: Props, send_span_setup: Callable[[Span, any], None] = None, receive_span_setup: Callable[[Span, any], None] = None, tracer: Tracer = None) -> Props: def fn(ctx): return OpenTracingFactory.get_context_with_open_tracing(ctx, send_span_setup, receive_span_setup) new_props = props.with_context_decorator([fn]) return OpenTracingFactory.get_props_with_open_tracing_sender(new_props, tracer)
async def test_request_actor_async_should_raise_timeout_exception_when_timeout_is_reached( ): with pytest.raises(TimeoutError) as excinfo: props = Props.from_func(empty_receive) pid = context.spawn(props) await context.request_async(pid, "", timedelta(seconds=1)) assert 'TimeoutError' in str(excinfo)
async def main(): context = RootContext() provider = InMemoryProvider() props = Props.from_producer(lambda: MyPersistenceActor(provider)) pid = context.spawn(props) input()
async def test_can_use_global_behaviour(): context = RootContext() test_actor_props = Props.from_producer(LightBulb) actor = context.spawn(test_actor_props) _ = await context.request_async(actor, PressSwitch()) assert await context.request_async(actor, HitWithHammer()) == "Smashed!" assert await context.request_async(actor, PressSwitch()) == "Broken" assert await context.request_async(actor, Touch()) == "OW!"
async def run_test(mailbox: Callable[..., AbstractMailbox]): props = Props.from_func(process_message) \ .with_mailbox(mailbox) pid = GlobalRootContext.spawn(props) for i in range(10000): await GlobalRootContext.send(pid, i) await GlobalRootContext.request_future(pid, 'stop')
async def test_can_change_states(): test_actor_props = Props.from_producer(LightBulb) context = RootContext() actor = context.spawn(test_actor_props) assert await context.request_async(actor, PressSwitch()) == "Turning on" assert await context.request_async(actor, Touch())== "Hot!" assert await context.request_async(actor, PressSwitch()) == "Turning off" assert await context.request_async(actor, Touch()) == "Cold"
def start(self) -> None: # self.__logger.log_debug('Started EndpointManager') props = Props().from_producer(EndpointSupervisor)\ .with_guardian_supervisor_strategy(Supervision().always_restart_strategy) self._endpoint_supervisor = GlobalRootContext().instance.spawn_named(props, 'EndpointSupervisor') self._endpoint_conn_evn_sub = GlobalEventStream().instance.subscribe(self.__on_endpoint_connected, EndpointConnectedEvent) self._endpoint_term_evn_sub = GlobalEventStream().instance.subscribe(self.__on_endpoint_terminated, EndpointTerminatedEvent)
def test_props_default_init(): props = Props() assert props.producer is None # TODO: change these value with concrete default instances #assert props.mailbox_producer is None #assert props.supervisor_strategy is None assert props.dispatcher is None assert props.middleware == [] assert props.middleware_chain is None
def create_transfer(self, actor_name: str, from_account: PID, to_account: PID, amount: float, persistence_id: str) -> PID: transfer_props = Props.from_producer(lambda: TransferProcess( from_account, to_account, amount, self._provider, persistence_id, self._availability)).with_child_supervisor_strategy( OneForOneStrategy( lambda pid, reason: SupervisorDirective.Restart, self._retry_attempts, None)) transfer = self._context.spawn_named(transfer_props, actor_name) return transfer
def __spawn_writer(self, address: str, context: AbstractContext) -> PID: writer_props = Props.from_producer(lambda: EndpointWriter(address, Remote().remote_config.channel_options, Remote().remote_config.call_options, Remote().remote_config.channel_credentials)) writer_props = writer_props.with_mailbox(lambda: EndpointWriterMailbox(Remote() .remote_config .endpoint_writer_batch_size)) writer = context.spawn(writer_props) return writer
def spawn_router_process(name: str, props: Props, parent: PID) -> PID: wg = threading.Event() router_state = self.create_router_state() p = props.with_producer(lambda: RouterActor(self, router_state, wg)) ctx = ActorContext(p, parent) mailbox = props.mailbox_producer() dispatcher = props.dispatcher process = RouterProcess(router_state, mailbox, wg) pid, absent = ProcessRegistry().try_add(name, process) if not absent: raise ProcessNameExistException(name, pid) ctx.my_self = pid mailbox.register_handlers(ctx, dispatcher) mailbox.post_system_message(Started()) mailbox.start() wg.wait() return pid
async def receive(self, context: AbstractContext): if context.children is None or len(context.children) == 0: props = Props.from_producer(lambda: ChildActor()) child = context.spawn(props) else: child = context.children[0] msg = context.message if isinstance(msg, Hello) or \ isinstance(msg, Recoverable) or \ isinstance(msg, Fatal): await context.forward(child) elif isinstance(msg, Terminated): print(f'Watched actor was Terminated, {msg.who}')
async def main(): async def child_fn(context: AbstractContext): print(f'{context.my_self.id}: MSG: {type(context.message)}') if isinstance(context.message, Started): raise Exception('child failure') child_props = Props.from_func(child_fn) async def root_fn(context: AbstractContext): print(f'{context.my_self.id}: MSG: {type(context.message)}') if isinstance(context.message, Started): context.spawn_named(child_props, 'child') elif isinstance(context.message, Terminated): print(f'Terminated {context.message.who}') root_props = Props.from_func(root_fn).with_child_supervisor_strategy( OneForOneStrategy(lambda pid, reason: SupervisorDirective.Escalate, 0, None)) root_context = RootContext() root_context.spawn_named(root_props, 'root') input()
def test_props_with(field, method, value): props = Props() with_method = getattr(props, method) new_props = with_method(value) results = [('producer', None), ('dispatcher', None), ('mailbox_producer', None), ('supervisor_strategy', None)] for r in results: field_name = r[0] prop_value = getattr(new_props, field_name) if field_name == field: assert prop_value == value else: assert prop_value == r[1]
async def main(): tracer = init_jaeger_tracer() opentracing.set_global_tracer(tracer) GlobalEventStream.subscribe(process_dead_letter_event, DeadLetterEvent) context = RootContext(middleware=[open_tracing_sender_middleware()]) props = Props.from_producer(lambda: ChildActor()) props = OpenTracingFactory.get_props_with_open_tracing(props) actor = context.spawn(props) await context.send(actor, Hello(who="Alex")) await asyncio.sleep(1) await GlobalRootContext.stop_future(actor) input()
def create_test_actor(strategy): events = {'process_started': threading.Event(), 'process_get_state': threading.Event(), 'process_get_index': threading.Event(), 'process_request_snapshot': threading.Event(), 'process_multiply': threading.Event()} actor_id = str(uuid.uuid4()) in_memory_provider = InMemoryProvider() props = Props.from_producer(lambda: ExamplePersistentActor(events, in_memory_provider, in_memory_provider, actor_id, strategy)).with_mailbox(MockMailbox) pid = root_context.spawn(props) return events, pid, props, actor_id, in_memory_provider
async def main(): context = LoggingRootDecorator(RootContext()) async def fn(context: AbstractContext): message = context.message if isinstance(message, str): print(f'Inside Actor: {message}') await context.respond("Yo!") props = Props.from_func(fn).with_context_decorator([ lambda c: LoggingDecorator(c, 'logger1'), lambda c: LoggingDecorator(c, 'logger2') ]) pid = context.spawn(props) res = await context.request_future(pid, 'Hello') print(f'Got result {res}') input()
async def start(argv): host = None port = None opts, args = getopt.getopt(argv, "hp", ["host=", "port="]) for opt, arg in opts: if opt == '--host': host = arg elif opt == '--port': port = arg Serialization().register_file_descriptor(DESCRIPTOR) context = RootContext() Remote().start(host, port) props = Props().from_producer(lambda: EchoActor(host, port)) Remote().register_known_kind('EchoActor', props) context.spawn_named(props, "EchoActorInstance") input()
async def receive(self, context: AbstractContext): msg = context.message if isinstance(msg, Started): pid = context.spawn(Props.from_producer(ScheduleGreetActor)) await self._scheduler.schedule_tell_once( timedelta(milliseconds=100), context.my_self, SimpleMessage('test 1')) await self._scheduler.schedule_tell_once( timedelta(milliseconds=200), context.my_self, SimpleMessage('test 2')) await self._scheduler.schedule_tell_once( timedelta(milliseconds=300), context.my_self, SimpleMessage('test 3')) await self._scheduler.schedule_tell_once( timedelta(milliseconds=400), context.my_self, SimpleMessage('test 4')) await self._scheduler.schedule_tell_once( timedelta(milliseconds=500), context.my_self, SimpleMessage('test 5')) await self._scheduler.schedule_request_once( timedelta(seconds=1), context.my_self, pid, Greet('Daniel')) await self._scheduler.schedule_tell_once(timedelta(seconds=5), context.my_self, Hello()) elif isinstance(msg, Hello): print( "Hello Once, let's give you a hickup every 0.5 second starting in 3 seconds!" ) await self._scheduler.schedule_tell_repeatedly( timedelta(seconds=3), timedelta(milliseconds=500), context.my_self, HickUp(), self._timer) elif isinstance(msg, HickUp): self._counter += 1 print('Hello!') if self._counter == 5: self._timer.trigger() await context.send(context.my_self, AbortHickUp()) elif isinstance(msg, AbortHickUp): print(f'Aborted hickup after {self._counter} times') print('All this was scheduled calls, have fun!') elif isinstance(msg, Greet): print(f'Thanks {msg.who()}') elif isinstance(msg, SimpleMessage): print(msg.msg())