Example #1
0
    def __init__(self, router, loop, signing_key, name='Node'):
        self.log = get_logger("{}.ReactorInterface".format(name))
        self.url = "ipc://{}-ReactorIPC-".format(name) + str(
            random.randint(0, pow(2, 16)))

        # Set instance vars
        self.router = router
        self.loop = loop
        asyncio.set_event_loop(
            self.loop)  # not sure if we need this (we shouldnt tbh)

        # Create zmq context and pair socket to communicate with reactor sub process
        self.context = zmq.asyncio.Context()
        self.socket = self.context.socket(zmq.PAIR)

        self.socket.bind(self.url)

        # Start reactor sub process
        self.proc = LProcess(target=self._start_daemon,
                             args=(self.url, signing_key, name))
        # self.proc.daemon = True
        self.proc.start()

        # Register signal handler to teardown
        signal.signal(signal.SIGTERM, self._signal_teardown)

        # Block execution of this proc until reactor proc is ready
        self.loop.run_until_complete(self._wait_child_rdy())
Example #2
0
def sub_proc_start():
    SLEEP_TIME = 10
    log = get_logger("SubProc")

    # log.debug("subproc spinning up subsubproc")
    p = LProcess(target=sub_sub_proc_start)
    p.daemon = True
    p.start()

    log.debug("sleeping for {}".format(SLEEP_TIME))
    time.sleep(SLEEP_TIME)
    log.debug("Done sleeping")
Example #3
0
def proc_start():
    SLEEP_TIME = 3
    log = get_logger("ProcStart")

    log.debug("proc starting subproc")
    p = LProcess(target=sub_proc_start)
    p.daemon = True
    p.start()
    log.debug("subproc started")

    # time.sleep(0.1)

    # p.join()

    log.critical("!!!!\n!!!!!\nABOUT TO EXPLODE\n!!!!!\n!!!!!")
    i = 10 / 0
Example #4
0
    def enter_any(self):
        # Create and start web server
        self.log.notice("Masternode creating REST server on port 8080")
        self.parent.tx_queue = q = Queue()
        self.parent.server = LProcess(target=start_webserver, args=(q, ))
        self.parent.server.start()

        # Create a worker to do transaction batching
        self.log.debug("Masternode creating transaction batcher process")
        self.parent.batcher = LProcess(target=TransactionBatcher,
                                       kwargs={
                                           'queue': q,
                                           'signing_key':
                                           self.parent.signing_key,
                                           'ip': self.parent.ip
                                       })
        self.parent.batcher.start()
Example #5
0
    def __init__(self, config_fn, assert_fn):
        super().__init__()
        self.log = get_logger("TestableProcess")

        self.config_fn = config_fn  # Function to configure object with mocks
        self.assert_fn = assert_fn  # Function to run assertions on inserted mock properties

        self.cmd_q = AioQueue()  # Used to pass commands into blocking object
        self.sig_q = Queue()  # Used to block on .start() and wait for child proc

        self.test_proc = LProcess(target=self._start_test, args=(self.sig_q, self.cmd_q))
        self.log.debug("Starting test")
        self.test_proc.start()

        self.log.debug("waiting for child ready sig")
        rdy = self.sig_q.get()
        self.log.debug("got rdy sig: {}".format(rdy))
Example #6
0
class ReactorInterface:
    def __init__(self, router, loop, signing_key, name='Node'):
        self.log = get_logger("{}.ReactorInterface".format(name))
        self.url = "ipc://{}-ReactorIPC-".format(name) + str(
            random.randint(0, pow(2, 16)))

        # Set instance vars
        self.router = router
        self.loop = loop
        asyncio.set_event_loop(
            self.loop)  # not sure if we need this (we shouldnt tbh)

        # Create zmq context and pair socket to communicate with reactor sub process
        self.context = zmq.asyncio.Context()
        self.socket = self.context.socket(zmq.PAIR)

        self.socket.bind(self.url)

        # Start reactor sub process
        self.proc = LProcess(target=self._start_daemon,
                             args=(self.url, signing_key, name))
        # self.proc.daemon = True
        self.proc.start()

        # Register signal handler to teardown
        signal.signal(signal.SIGTERM, self._signal_teardown)

        # Block execution of this proc until reactor proc is ready
        self.loop.run_until_complete(self._wait_child_rdy())

    def start_reactor(self, tasks):
        """
        Method to kick off the event loop and start listening to the ReactorDaemon. No callbacks from the ReactorDaemon
        are read until this method gets invoked. This blocks on whatever process its called on, and thus should be
        called AFTER any other application set up (such as starting the state machine so it enters its initial state).
        Generally speaking, this should be the last command run during application bootstrap as it blocks
        the process and opens up the system to receiving messages from ReactorDaemon (although we can still SEND msgs
        to ReactorDaemon before this method is called).

        Optionally, a list of additional tasks (asyncio Future/Task objects) can be passed in which will be included in
        the loop's run_until_complete.
        """
        try:
            self.recv_fut = asyncio.gather(self._recv_messages(), *tasks)
            self.loop.run_until_complete(self.recv_fut)
        except Exception as e:
            self.log.error("Exception in main event loop: {}".format(
                traceback.format_exc()))
            self.log.info("Tearing down from runtime loop exception")
            self._teardown()

    def _signal_teardown(self, signal, frame):
        print("Main process got kill signal: {}   ... with frame: {} ".format(
            signal, frame))
        self._teardown()
        sys.exit(0)

    def _teardown(self):
        """
        Close sockets. Close Event Loop. Teardown. Bless up.
        """
        self.log.info(
            "[MAIN PROC] Tearing down Reactor Interface process (the main process)"
        )

        # TODO -- why is this complaining of no attribute 'recv_fut' ???
        # self.log.debug("Canceling recv_messages future")
        # self.recv_fut.cancel()
        # self.loop.call_soon_threadsafe(self.recv_fut.cancel)

        self.log.debug("Closing pair socket")
        self.socket.close()

        # self.log.debug("Closing event loop")
        # self.loop.call_soon_threadsafe(self.loop.stop)

    def _start_daemon(self, url, sk, name):
        """
        Should be for internal use only.
        The target method for the ReactorDaemon subprocess (this code gets run in a child process). This simply creates
        a ReactorDaemon instance, passing in the URL for the communication socket between ReactorInterface
        and ReactorDaemon. This process 'blocks' as soon as the ReactorDaemon is created.

        :param url: The url for the IPC pair socket between the ReactorInterface and ReactorDaemon
        """
        reactor = ReactorDaemon(url=url, sk=sk, name=name)

    async def _wait_child_rdy(self):
        """
        Should be for internal use only.
        Method that awaits a ready signal from the ReactorDaemon process. This is run_until_complete after we start
        the ReactorDaemon process to block execution of the main process until the ReactorDaemon sends a ready signal.
        This ensures that we do not try to send commands to the ReactorDaemon process before it is ready.
        """
        self.log.debug("Waiting for ready sig from child proc...")
        msg = await asyncio.wait_for(self.socket.recv(), 40)
        assert msg == CHILD_RDY_SIG, "Got unexpected rdy sig from child proc (got '{}', but expected '{}')" \
            .format(msg, CHILD_RDY_SIG)
        self.log.debug("Got ready sig from child proc: {}".format(msg))

    async def _recv_messages(self):
        """
        Should be for internal use only.
        Starts listening to messages from the ReactorDaemon. This method gets run_until_complete by
        invoking .start_reactor on the ReactorInterface object.
        """
        try:
            self.log.debug(
                "~~ Reactor listening to messages from ReactorDaemon ~~")
            while True:
                self.log.debug("Waiting for callback...")
                msg = await self.socket.recv()
                callback = ReactorCommand.from_bytes(msg)
                self.log.debug("Got callback cmd <{}>".format(callback))
                self.router.route_callback(callback)
        except asyncio.CancelledError:
            self.log.debug("_recv_messages future canceled!")

    def notify_resume(self):
        self.log.info("NOTIFIY READY")
        # TODO -- implement (add queue of tx, flush on notify ready, pause on notify_pause

    def notify_pause(self):
        self.log.info("NOTIFY PAUSE")
        # TODO -- implement

    def send_cmd(self, cmd: ReactorCommand):
        assert isinstance(
            cmd, ReactorCommand
        ), "Only ReactorCommand instances can sent through the reactor"
        self.socket.send(cmd.serialize())
Example #7
0
def proc_start():
    SLEEP_TIME = 3
    log = get_logger("ProcStart")

    log.debug("proc starting subproc")
    p = LProcess(target=sub_proc_start)
    p.daemon = True
    p.start()
    log.debug("subproc started")

    # time.sleep(0.1)

    # p.join()

    log.critical("!!!!\n!!!!!\nABOUT TO EXPLODE\n!!!!!\n!!!!!")
    i = 10 / 0


if __name__ == '__main__':
    log = get_logger('MAIN')
    print("\n\n\n THIS IS A PRINT LETS GOOOOOO \n\n\n")

    log.info("starting process")
    p = LProcess(target=proc_start)
    p.start()

    print("hi this is a test")
    print("lets go my friend")
    # i = 10 / 0
Example #8
0
class TestableReactor:
    def __init__(self, config_fn, assert_fn):
        super().__init__()
        self.log = get_logger("TestableProcess")

        self.config_fn = config_fn  # Function to configure object with mocks
        self.assert_fn = assert_fn  # Function to run assertions on inserted mock properties

        self.cmd_q = AioQueue()  # Used to pass commands into blocking object
        self.sig_q = Queue()  # Used to block on .start() and wait for child proc

        self.test_proc = LProcess(target=self._start_test, args=(self.sig_q, self.cmd_q))
        self.log.debug("Starting test")
        self.test_proc.start()

        self.log.debug("waiting for child ready sig")
        rdy = self.sig_q.get()
        self.log.debug("got rdy sig: {}".format(rdy))

    def _start_test(self, rdy_sig_q, cmd_q):
        async def recv_cmd():
            while True:
                log.critical("waiting for cmd")
                cmd = await cmd_q.coro_get()
                func, args, kwargs = cmd
                log.critical("got cmd: {}".format(cmd))
                log.critical("cmd name: {}\nkwargs: {}".format(func, kwargs))

                getattr(reactor, func)(*args, **kwargs)

        async def check_assertions():
            self.log.debug("Starting assertion checks")
            timeout = TEST_TIMEOUT
            while timeout > 0:
                try:
                    self.assert_fn(reactor)
                    self.log.critical("Assertions successful with {} left!".format(timeout))
                    rdy_sig_q.put("BIG TIME PLAYERS MAKE BIG TIME PLAYS")
                    break
                except Exception as e:
                    self.log.warning("assertion failed: {}".format(e))

                await asyncio.sleep(TEST_CHECK_FREQ)
                timeout -= TEST_CHECK_FREQ

        log = get_logger("TesterTarget")
        loop = asyncio.new_event_loop()
        mock_parent = MagicMock()

        log.debug("creating reactor")
        reactor = ReactorInterface(mock_parent, loop)

        log.info("setting mock config")
        reactor = self.config_fn(reactor)

        log.critical("mock property: {}".format(reactor._run_callback))

        log.debug("sending ready sig to parent")
        rdy_sig_q.put('ready')

        log.debug("starting TestableProcess event loop")
        loop.run_until_complete(asyncio.gather(recv_cmd(), check_assertions()))