async def test_sentry_extras_provider_subscriber(self, wampclient: WAMPClient,
                                                     context: Context, monkeypatch):
        class DummyReporter(ExceptionReporter):
            def report_exception(self, ctx: Context, exception: BaseException, message: str,
                                 extra: Dict[str, Any]) -> None:
                errors.append((exception, message, extra))

        def handler(ctx):
            ctx.loop.call_soon(event.set)
            raise Exception('foo')

        event = asyncio.Event()
        errors = []
        context.add_resource(DummyReporter(), types=[ExceptionReporter])
        context.add_resource(WAMPExtrasProvider(), types=[ExtrasProvider])
        await wampclient.subscribe(handler, 'dummytopic')
        monkeypatch.setattr('asphalt.wamp.extras_providers.SENTRY_CLASS_NAME',
                            qualified_name(DummyReporter))
        await wampclient.publish('dummytopic', options=dict(acknowledge=True, exclude_me=False))

        await event.wait()
        assert len(errors) == 1
        exc, message, extra = errors[0]
        assert type(exc) is Exception
        assert str(exc) == 'foo'
        assert message == "Error running subscription handler for topic 'dummytopic'"
        assert extra == {'extra': {'topic': 'dummytopic'},
                         'user_context': {'auth_role': 'authorized_users',
                                          'id': 'device1',
                                          'session_id': wampclient.session_id}
                         }
Example #2
0
    async def start(self, ctx: Context):
        if isinstance(self.commit_executor, str):
            self.commit_executor = await ctx.request_resource(Executor, self.commit_executor)
        elif self.commit_executor is None:
            self.commit_executor = ThreadPoolExecutor(self.commit_executor_workers)
            ctx.add_teardown_callback(self.commit_executor.shutdown)

        for resource_name, context_attr, bind, factory, ready_callback in self.session_factories:
            if ready_callback:
                retval = ready_callback(bind, factory)
                if isawaitable(retval):
                    await retval

            engine = bind if isinstance(bind, Engine) else bind.engine
            ctx.add_resource(engine, resource_name)
            ctx.add_resource(factory, resource_name)
            ctx.add_resource_factory(partial(self.create_session, factory=factory),
                                     [Session], resource_name, context_attr)
            logger.info('Configured SQLAlchemy session maker (%s / ctx.%s; dialect=%s)',
                        resource_name, context_attr, bind.dialect.name)

        await yield_()

        for resource_name, context_attr, bind, factory, ready_callback in self.session_factories:
            if isinstance(bind, Engine):
                bind.dispose()

            logger.info('SQLAlchemy session maker (%s / ctx.%s) shut down', resource_name,
                        context_attr)
    async def test_report_applicationerror(self, wampclient: WAMPClient, context: Context,
                                           custom_exception):
        class DummyReporter(ExceptionReporter):
            def report_exception(self, ctx: Context, exception: BaseException, message: str,
                                 extra: Dict[str, Any]) -> None:
                errors.append((exception, message, extra))

        class CustomError(Exception):
            pass

        def handler(ctx):
            if custom_exception:
                raise CustomError
            else:
                raise ApplicationError('dummy.error')

        errors = []
        context.add_resource(DummyReporter(), types=[ExceptionReporter])
        wampclient.map_exception(CustomError, 'dummy.error')
        await wampclient.register(handler, 'dummyprocedure')

        with pytest.raises(CustomError):
            await wampclient.call('dummyprocedure')

        assert not errors
    async def test_sentry_extras_provider_procedure(self, wampclient: WAMPClient,
                                                    context: Context, monkeypatch):
        class DummyReporter(ExceptionReporter):
            def report_exception(self, ctx: Context, exception: BaseException, message: str,
                                 extra: Dict[str, Any]) -> None:
                errors.append((exception, message, extra))

        def handler(ctx):
            raise Exception('foo')

        errors = []
        context.add_resource(DummyReporter(), types=[ExceptionReporter])
        context.add_resource(WAMPExtrasProvider(), types=[ExtrasProvider])
        await wampclient.register(handler, 'dummyprocedure')
        monkeypatch.setattr('asphalt.wamp.extras_providers.SENTRY_CLASS_NAME',
                            qualified_name(DummyReporter))
        with pytest.raises(ApplicationError):
            await wampclient.call('dummyprocedure')

        assert len(errors) == 1
        exc, message, extra = errors[0]
        assert type(exc) is Exception
        assert str(exc) == 'foo'
        assert message == "Error running handler for procedure 'dummyprocedure'"
        assert extra == {'extra': {'procedure': 'dummyprocedure'},
                         'user_context': {'auth_role': 'authorized_users',
                                          'id': 'device1',
                                          'session_id': wampclient.session_id}
                         }
 def test_get_resources(self, context):
     context.add_resource(9, 'foo')
     context.add_resource_factory(lambda ctx: len(ctx.context_chain), int, 'bar')
     context.require_resource(int, 'bar')
     subctx = Context(context)
     subctx.add_resource(4, 'foo')
     assert subctx.get_resources(int) == {1, 4}
    async def start(self, ctx: Context):
        for resource_name, context_attr, serializer in self.serializers:
            types = [Serializer, type(serializer)]
            if isinstance(serializer, CustomizableSerializer):
                types.append(CustomizableSerializer)

            ctx.add_resource(serializer, resource_name, context_attr, types=types)
            logger.info('Configured serializer (%s / ctx.%s; type=%s)', resource_name,
                        context_attr, serializer.mimetype)
Example #7
0
    async def start(self, ctx: Context):
        for resource_name, context_attr, serializer in self.serializers:
            types = [Serializer, type(serializer)]
            if isinstance(serializer, CustomizableSerializer):
                types.append(CustomizableSerializer)

            ctx.add_resource(serializer, resource_name, context_attr, types=types)
            logger.info('Configured serializer (%s / ctx.%s; type=%s)', resource_name,
                        context_attr, serializer.mimetype)
    async def start(self, ctx: Context):
        for resource_name, context_attr, client in self.clients:
            ctx.add_resource(client, resource_name, context_attr)
            logger.info('Configured Memcached client (%s / ctx.%s)', resource_name, context_attr)

        await yield_()

        for resource_name, context_attr, client in self.clients:
            client.close()
            logger.info('Memcached client (%s) shut down', resource_name)
Example #9
0
    async def start(self, ctx: Context):
        for resource_name, context_attr, client in self.clients:
            ctx.add_resource(client, resource_name, context_attr)
            logger.info('Configured Memcached client (%s / ctx.%s)',
                        resource_name, context_attr)

        await yield_()

        for resource_name, context_attr, client in self.clients:
            client.close()
            logger.info('Memcached client (%s) shut down', resource_name)
    async def start(self, ctx: Context):
        for resource_name, store in self.stores:
            await store.start(ctx)
            ctx.add_resource(store, resource_name)
            logger.info('Configured feed state store (%s; class=%s)', resource_name,
                        qualified_name(store))

        for resource_name, context_attr, config in self.feeds:
            feed = await create_feed(ctx, **config)
            ctx.add_resource(feed, resource_name, context_attr, types=[type(feed), FeedReader])
            logger.info('Configured feed (%s / ctx.%s; url=%s)', resource_name, context_attr,
                        feed.url)
    async def start(self, ctx: Context):
        for resource_name, context_attr, server in self.servers:
            await server.start(ctx)
            ctx.add_resource(server, resource_name, context_attr, BaseWebServer)
            logger.info('Started %s (%s / ctx.%s)', server.__class__.__name__, resource_name,
                        context_attr)

        await yield_()

        for resource_name, context_attr, server in self.servers:
            await server.shutdown()
            logger.info('Shut down %s (%s)', server.__class__.__name__, resource_name)
Example #12
0
    async def start(self, ctx: Context):
        for resource_name, context_attr, client in self.clients:
            await client.start(ctx)
            ctx.add_resource(client, resource_name, context_attr)
            logger.info(
                'Configured InfluxDB client (%s / ctx.%s; base_urls=%r)',
                resource_name, context_attr, client.base_urls)

        await yield_()

        for resource_name, context_attr, client in self.clients:
            logger.info('InfluxDB client (%s) shut down', resource_name)
    async def start(self, ctx: Context):
        for resource_name, context_attr, mailer in self.mailers:
            await mailer.start(ctx)
            ctx.add_resource(mailer, resource_name, context_attr,
                             [Mailer, type(mailer)])
            logger.info('Configured mailer (%s / ctx.%s; class=%s)',
                        resource_name, context_attr, mailer.__class__.__name__)

        await yield_()

        for resource_name, context_attr, mailer in self.mailers:
            logger.info('Mailer (%s) stopped', resource_name)
    async def start(self, ctx: Context):
        # Autobahn uses txaio to bridge the API gap between asyncio and Twisted so we need to set
        # it up for asyncio here
        txaio.use_asyncio()
        txaio.config.loop = ctx.loop

        ctx.add_resource(WAMPExtrasProvider(), 'wamp', types=[ExtrasProvider])

        for resource_name, context_attr, client in self.clients:
            await client.start(ctx)
            ctx.add_resource(client, resource_name, context_attr)
            logger.info('Configured WAMP client (%s / ctx.%s; host=%s; port=%d; realm=%s)',
                        resource_name, context_attr, client.host, client.port, client.realm)

        await yield_()

        for resource_name, context_attr, client in self.clients:
            await client.stop()
            logger.info('Shut down WAMP client (%s)', resource_name)
Example #15
0
    async def start(self,
                    ctx: Context) -> AsyncGenerator[None, Exception | None]:
        if self.ready_callback:
            retval = self.ready_callback(self.bind, self.sessionmaker)
            if isawaitable(retval):
                await retval

        ctx.add_resource(self.engine, self.resource_name)
        ctx.add_resource(self.sessionmaker, self.resource_name)
        if isinstance(self.engine, AsyncEngine):
            ctx.add_resource_factory(
                self.create_async_session,
                [AsyncSession],
                self.resource_name,
            )
        else:
            self.commit_executor = ThreadPoolExecutor(
                self.commit_executor_workers)
            ctx.add_teardown_callback(self.commit_executor.shutdown)

            ctx.add_resource_factory(
                self.create_session,
                [Session],
                self.resource_name,
            )

        logger.info(
            "Configured SQLAlchemy resources (%s; dialect=%s, driver=%s)",
            self.resource_name,
            self.bind.dialect.name,
            self.bind.dialect.driver,
        )

        yield

        if isinstance(self.bind, Engine):
            self.bind.dispose()
        elif isinstance(self.bind, AsyncEngine):
            await self.bind.dispose()

        logger.info("SQLAlchemy resources (%s) shut down", self.resource_name)