async def setUp(self) -> None:
        self.addr_db = InMemoryAddressBookDB()
        self.service = AddressBookService(self.addr_db)
        self.service.start()

        self.address_data = address_data_suite()
        for nickname, addr in self.address_data.items():
            await self.addr_db.create_address(addr, nickname)
Exemple #2
0
    async def setUp(self) -> None:
        self.addr_db = InMemoryAddressBookDB()
        tracing.set_trace_collectors(
            [tracing.CummulativeFunctionTimeProfiler()])
        self.service = AddressBookService(self.addr_db)
        self.service.start()

        self.address_data = address_data_suite()
        for nickname, addr in self.address_data.items():
            await self.addr_db.create_address(addr, nickname)
Exemple #3
0
    def get_app(self) -> tornado.web.Application:
        # get_app is the hook that Tornado Test uses to get app under test
        addr_db = create_addressbook_db(TEST_CONFIG['addr-db'])
        addr_service = AddressBookService(addr_db)

        addr_service.start()
        atexit.register(lambda: addr_service.stop())

        return make_addrservice_app(service=addr_service,
                                    config=TEST_CONFIG,
                                    debug=True)
Exemple #4
0
    async def setUp(self) -> None:
        logging.config.dictConfig(TEST_CONFIG['logging'])
        logger = logging.getLogger(LOGGER_NAME)

        self.service = AddressBookService(config=TEST_CONFIG, logger=logger)
        self.service.start()

        self.address_data = address_data_suite()
        for nickname, val in self.address_data.items():
            addr = AddressEntry.from_api_dm(val)
            await self.service.addr_db.create_address(addr, nickname)
Exemple #5
0
class AddressBookServiceWithInMemoryDBTest(asynctest.TestCase):
    async def setUp(self) -> None:
        self.addr_db = InMemoryAddressBookDB()
        tracing.set_trace_collectors(
            [tracing.CummulativeFunctionTimeProfiler()])
        self.service = AddressBookService(self.addr_db)
        self.service.start()

        self.address_data = address_data_suite()
        for nickname, addr in self.address_data.items():
            await self.addr_db.create_address(addr, nickname)

    async def tearDown(self) -> None:
        self.service.stop()

    def test_uptime(self) -> None:
        self.assertGreater(self.service.uptime_millis(), 0)

    @asynctest.fail_on(active_handles=True)
    async def test_status(self) -> None:
        status = await self.service.status()
        self.assertTrue(status['ready'])
        self.assertGreater(status['uptime'], 0)

    @asynctest.fail_on(active_handles=True)
    async def test_get_address(self) -> None:
        for nickname, addr in self.address_data.items():
            value = await self.service.get_address(nickname)
            self.assertEqual(addr, value)

    @asynctest.fail_on(active_handles=True)
    async def test_get_all_addresses(self) -> None:
        all_addr = await self.service.get_all_addresses()
        self.assertEqual(len(all_addr), 2)

    @asynctest.fail_on(active_handles=True)
    async def test_post_put_delete_address(self) -> None:
        nicknames = list(self.address_data.keys())
        self.assertGreaterEqual(len(nicknames), 2)

        addr0 = self.address_data[nicknames[0]]
        key = await self.service.post_address(addr0)
        val = await self.service.get_address(key)
        self.assertEqual(addr0, val)

        addr1 = self.address_data[nicknames[1]]
        await self.service.put_address(key, addr1)
        val = await self.service.get_address(key)
        self.assertEqual(addr1, val)

        await self.service.delete_address(key)

        with self.assertRaises(KeyError):
            await self.service.get_address(key)
Exemple #6
0
def run_server(
    app: tornado.web.Application,
    service: AddressBookService,
    config: Dict,
    port: int,
    logger: logging.Logger,
    debug: bool,
):
    name = config['service']['name']

    # Install async IO event loop instead of Tornado's IO loop for standard
    # async/await code and Tornado to work in same even loop.
    tasyncio.AsyncIOMainLoop().install()

    # Register loop.stop() as signal handler
    # In 3.6, shutting down gracefully is a lot simpler:
    #
    # try:
    #     loop.run_forever()
    # finally:
    #     loop.run_until_complete(loop.shutdown_asyncgens())
    #     loop.close()
    loop = asyncio.get_event_loop()
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, loop.stop)

    # Start auth, caller's start_up and server
    service.start()

    # Start http server
    http_server_args = {'decompress_request': True}

    http_server = app.listen(port, '', **http_server_args)
    msg = 'Starting {} on port {} ...'.format(name, port)
    logger.info(msg)

    # Start event loop
    # asyncio equivalent of tornado.ioloop.IOLoop.current().start()
    loop.run_forever()

    # Begin shutdown after loop.stop() upon receiving signal
    msg = 'Shutting down {}...'.format(name)
    logger.info(msg)

    http_server.stop()
    # Run unfinished tasks and stop event loop
    loop.run_until_complete(asyncio.gather(*asyncio.Task.all_tasks()))
    service.stop()
    loop.close()

    # Service stopped
    msg = 'Stopped {}.'.format(name)
    logger.info(msg)
Exemple #7
0
class AddressBookServiceWithInMemoryDBTest(asynctest.TestCase):
    async def setUp(self) -> None:
        logging.config.dictConfig(TEST_CONFIG['logging'])
        logger = logging.getLogger(LOGGER_NAME)

        self.service = AddressBookService(config=TEST_CONFIG, logger=logger)
        self.service.start()

        self.address_data = address_data_suite()
        for nickname, val in self.address_data.items():
            addr = AddressEntry.from_api_dm(val)
            await self.service.addr_db.create_address(addr, nickname)

    async def tearDown(self) -> None:
        self.service.stop()

    @asynctest.fail_on(active_handles=True)
    async def test_get_address(self) -> None:
        for nickname, addr in self.address_data.items():
            value = await self.service.get_address(nickname)
            self.assertEqual(addr, value)

    @asynctest.fail_on(active_handles=True)
    async def test_get_all_addresses(self) -> None:
        all_addr = {}
        async for nickname, addr in self.service.get_all_addresses():
            all_addr[nickname] = addr
        self.assertEqual(len(all_addr), 2)

    @asynctest.fail_on(active_handles=True)
    async def test_crud_address(self) -> None:
        nicknames = list(self.address_data.keys())
        self.assertGreaterEqual(len(nicknames), 2)

        addr0 = self.address_data[nicknames[0]]
        key = await self.service.create_address(addr0)
        val = await self.service.get_address(key)
        self.assertEqual(addr0, val)

        addr1 = self.address_data[nicknames[1]]
        await self.service.update_address(key, addr1)
        val = await self.service.get_address(key)
        self.assertEqual(addr1, val)

        await self.service.delete_address(key)

        with self.assertRaises(KeyError):
            await self.service.get_address(key)
def make_addrservice_app(
    config: Dict,
    debug: bool,
    logger: logging.Logger = logging.getLogger(LOGGER_NAME)
) -> Tuple[AddressBookService, tornado.web.Application]:
    service = AddressBookService.from_config(config)

    app = tornado.web.Application(
        [
            # Heartbeat
            (r'/healthz/?', LivenessRequestHandler,
             dict(service=service, config=config, logger=logger)),  # noqa
            (r'/readiness/?', ReadinessRequestHandler,
             dict(service=service, config=config, logger=logger)),  # noqa
            # Address Book endpoints
            (ADDRESSBOOK_REGEX, AddressBookRequestHandler,
             dict(service=service, config=config, logger=logger)),  # noqa
            (ADDRESSBOOK_ENTRY_REGEX, AddressBookEntryRequestHandler,
             dict(service=service, config=config, logger=logger))  # noqa
        ],
        compress_response=True,  # compress textual responses
        log_function=log_function,  # log_request() uses it to log results
        serve_traceback=debug,  # it is passed on as setting to write_error()
        # TODO: Exercise: add here suitable values for default_handler_class
        # and default_handler_args parameters to hook in DefaultRequestHandler
    )

    return service, app
Exemple #9
0
def run_server(app: tornado.web.Application, service: AddressBookService,
               config: Dict, port: int, debug: bool, logger: logging.Logger):
    name = config['service']['name']
    loop = asyncio.get_event_loop()
    loop.set_task_factory(context.task_factory)

    # Start AddressBook service
    service.start()

    # Bind http server to port
    http_server_args = {'decompress_request': True}
    http_server = app.listen(port, '', **http_server_args)
    logutils.log(logger,
                 logging.INFO,
                 message='STARTING',
                 service_name=name,
                 port=port)

    try:
        # Start asyncio IO event loop
        loop.run_forever()
    except KeyboardInterrupt:
        # signal.SIGINT
        pass
    finally:
        loop.stop()
        logutils.log(logger,
                     logging.INFO,
                     message='SHUTTING DOWN',
                     service_name=name)
        http_server.stop()
        # loop.run_until_complete(asyncio.gather(*asyncio.Task.all_tasks()))
        loop.run_until_complete(loop.shutdown_asyncgens())
        service.stop()
        loop.close()
        logutils.log(logger,
                     logging.INFO,
                     message='STOPPED',
                     service_name=name)
Exemple #10
0
def main(args=parse_args()):
    '''
    Starts the Tornado server serving Address Book on the given port
    '''

    config = yaml.load(args.config.read(), Loader=yaml.SafeLoader)

    # First thing: set logging config
    logging.config.dictConfig(config['logging'])
    logger = logging.getLogger(LOGGER_NAME)

    addr_db = create_addressbook_db(config['addr-db'])
    addr_service = AddressBookService(addr_db)
    addr_app = make_addrservice_app(addr_service, config, args.debug)

    run_server(
        app=addr_app,
        service=addr_service,
        config=config,
        port=args.port,
        logger=logger,
        debug=args.debug,
    )